Использование общедоступных и частных методов внутри своего класса в Perl 6

Если у меня есть общедоступный метод, я могу вызвать его внутри своего класса, используя как $.name и self.name:

class TEST {
  has Int $.a;

  method b($x) {
    return $!a * $x;
  }

  method c($y) {
    return self.b($y) * 3; # or $.b($y)
  }
}

my $m = TEST.new(a => 10);
say $m.c(2); # 60

Но если я сделаю b приватным методом, я могу назвать его только с помощью self!b, а не $!b, иначе я получаю следующее сообщение об ошибке:

Attribute $!b not declared in class TEST

Что за этим правилом? Каковы правила вызова метода внутри его собственного класса?

Ответы

Ответ 1

Атрибут всегда можно назвать $!foo в классе. Если вы это сделаете, то код будет сгенерирован для прямого доступа к самому атрибуту, и любые классы, подклассифицирующие ваш класс, не смогут изменить это поведение.

Если вы используете в объявлении класса has $.foo, это означает, что общедоступный аксессор (и если вы добавите is rw он также может работать как мутатор).

Когда вы используете $.foo в своем коде в противном случае, это точно так же, как $( self.foo ). Это означает, что он вызовет метод foo on self и itemize возвращаемое значение (сделайте его одной "вещью", если он еще не был). Это пойдет не так, если вы определили свой атрибут с помощью $!foo и вы не предоставили method foo самостоятельно.

Это еще больше: $.bar действительно означает self.bar: вам нужно только иметь метод, существующий в bar имени, который вообще не может быть связан с каким-либо атрибутом.

Если вы определяете частный метод !baz ! просто указывает на неприкосновенность частной жизни метода, а это означает, что вам нужно называть его действительно как self!baz. Для этого нет короткого синтаксиса.

Лично мне не нравится тот факт, что вы можете сказать $.zippo даже если zippo не является атрибутом. Но я боюсь, что корабль отплыл. Но это поведение вызывает у вас путаницу :-(

Итак, что из-за правила не иметь короткий синтаксис для вызова частного метода? Не уверен, я думаю, действительно, что $!foo уже был использован для обозначения прямого доступа к атрибуту и предоставить вам ошибку времени компиляции, если атрибут не существует.

Надеюсь, что это ответ на ваш вопрос!