Inheriting private attributes in Perl 6

2020-04-03 02:34发布

I can't find anything in the docs, but it seems that there is no access in a subclass to its superclass's private variables. Am I right?

class A {
  has $!a;
}

class B is A {
  has $.b;

  method set_a($x) {
    $!a = $x;
  }
}

my $var = B.new();
$var.set_a(5);
say $var.a;

This gives an error message:

Attribute $!a not declared in class B

BTW where to read about Classes in the docs? I have only found a rather short section Classes and Objects.

标签: oop raku
1条回答
我命由我不由天
2楼-- · 2020-04-03 03:19

In Perl 6, an attribute declared in a class is accessible only within that class. This means one can confidently refactor the state in the class without having to worry about any uses of that state outside of the class.

Subclasses do not receive any special access with regards to attributes. Some languages provide a protected modifier. This does not exist in Perl 6, by design. Either something is private to that class, or is exposed (like has $.a) to the outside world, since:

  1. So far as that class is concerned, a subclass is part of the outside world.
  2. Given the general advice is to "prefer composition over inheritance", it seems strange to privilege inheritance, or provide a mechanism that frustrates refactoring from inheritance to composition.

Attributes in a role, by contrast, are composed into the class, working as if they had been declared in the class itself. Therefore, an attribute from a composed role may be used in the class body. If looking to write re-usable pieces of functionality in an OO context, it's more typical to use roles and composition in Perl 6, not inheritance. Indeed, writing the original code as:

role A {
  has $!a;
}

class B does A {
  has $.b;

  method set_a($x) {
    $!a = $x;
  }
  method a() { $!a }
}

my $var = B.new();
$var.set_a(5);
say $var.a;

Works as desired.

查看更多
登录 后发表回答