Ответ Кристофа уже отличный. Мой ответ - это попытка дать некоторый контекст на небольшом конкретном примере.
Как утверждает Кристоф, в Raku вызывающая сторона метода передается как неявный первый позиционный аргумент, который затем становится доступным для тела метода как self
:
class Person {
has $.name;
method greet( Person $B, $greeting = 'Hello' ) {
$A.name ~ ": $greeting, " ~ $B.name ~ '.'
}
}
my $john = Person.new(name => 'John');
my $dana = Person.new(name => 'Dana');
say $john.greet($dana, 'Good morning'); # «John: Good morning, Dana.»
Если вы хотите привязать его к чему-то еще, используйте синтаксис method meth-name( invocant : param1, param2, ..., param3) { ... }
, где param1, param2, ..., param3
- обычные параметры (как позиционные, так и именованные), которые вы объявляете в методе. Как утверждает Кристоф, этот синтаксис «необходим даже в случае [подписи без параметров], чтобы можно было устранить неоднозначность подписи с помощью обычного позиционного параметра». Следовательно:
# Person A greets person B.
method greet( $A : Person $B, $greeting = 'Hello' ) {
self.name ~ ": $greeting, " ~ $B.name ~ '.'
}
Вы можете пойти еще дальше и ввести вызывающий, не обязательно потому, что он нужен, а потому, что он делает сигнатуру метода более наглядной:
# Person A greets person B.
method greet( Person $A : Person $B, $greeting = 'Hello' ) {
$A.name ~ ": $greeting, " ~ $B.name ~ '.'
}
Если вы не хотите, чтобы метод greet
принимал объекты типа (например, Person
), а вместо этого принимал только экземпляры объектов этого типа (например, Person.new
), вы можете использовать type smily :D
. Таким образом:
# Person A greets person B.
method greet( Person:D $A : Person $B, $greeting = 'Hello' ) {
$A.name ~ ": $greeting, " ~ $B.name ~ '.'
}
Смайлы типа :D
(определены для D), :U
(для U ndefined) и :_
(это неявный смайлик для типа, который не использует ни :D
, ни :U
).
Если вы удалите явный активатор (и вернетесь к использованию self
) из сигнатуры метода, вы получите что-то похожее на то, что у вас есть в вашем вопросе. Здесь я просто использую пробелы, чтобы это выглядело менее устрашающе:
method greet( Person:D : Person $B, $greeting = 'Hello' ) {
self.name ~ ": $greeting, " ~ $B.name ~ '.'
}
Приложение:
В Raku методы могут быть ограничены вызовом только для экземпляров объекта класса (для методов объекта) или только для самого класса (для методов класса); вам просто нужно добавить :D
смайлик к имени класса для методов объекта и :U
смайлик к имени класса для методов класса:
method object-method( CLASSNAME:D : ) { ... }
method class-method( CLASSNAME:U : ) { ... }
Однако это не так широко, как могло бы быть, вместо этого вы можете использовать переменную времени компиляции _ 22_, который определяет текущий класс и, таким образом, избавляет от необходимости указывать имя класса. Например, чтобы ограничить greet
вызовом только для объектов экземпляра Person
:
method greet( ::?CLASS:D: Person $B, $greeting = 'Hello' ) {
self.name ~ ": $greeting, " ~ $B.name ~ '.'
}
Как всегда, если вас смущают двоеточия, вы всегда можете поместить пробел между тем, к чему прикреплен тип smily, и оставшимся :
, чтобы сделать вещи более очевидными, например:
method greet( ::?CLASS:D : Person $B, $greeting = 'Hello' ) {
self.name ~ ": $greeting, " ~ $B.name ~ '.'
}
person
Luis F. Uceta
schedule
26.01.2020