Метод класса и метод класса Perl
При изучении других языков часто существует разница между методом класса и объектным методом.
Я знаю, что в Perl класс слабый. Есть ли разница между методом класса и методом объекта?
Я знаю, что наиболее часто используемый метод класса может быть методом класса new
. В Perl я могу вызвать все методы с именем пакета, но не с объектом пакета. Почему это?
Ответы
Ответ 1
Полезная страница perlobj
:
Когда вы вызываете метод, предмет в левой части стрелки передается как первый аргумент метода. Это означает, что когда мы вызываем Critter->new()
, метод new()
получает строку "Critter"
в качестве своего первого аргумента. Когда мы вызываем $fred->speak()
, переменная $fred
передается как первый аргумент speak()
.
Другими словами, Perl не делает резкое различие между методами класса и методами экземпляра. Они отличаются тем, что передается как первый аргумент метода, и если некоторые методы фактически не заботятся о том, что передается в качестве первого аргумента, тогда вы можете обмануть и называть их "неправильным" способом.
Perl все равно. Обычно этого не происходит.
Ответ 2
@qwrrty ответ - хорошее объяснение ситуации, но из комментариев у меня создается впечатление, что даже если Perl делает небольшое различие между объектными и классными методами, @JackXu будет как такое различие.
Если вы хотите сделать такое различие, тогда решение должно проверить $_[0]
, чтобы увидеть, является ли он объектом или строкой, и вести себя надлежащим образом (например, вызывать исключение, если метод объекта вызывается с именем класса как первый параметр).
Существуют различные модули сигнатур метода, доступные в CPAN, которые делают это глупо легко, в соответствии с:
package Foo;
method xxx (Object $self: Int $x) {
...;
}
Foo->xxx(1); # throws an error because "Foo" is not an object
Я собираюсь сутуреть свое решение для такого рода вещей - Moops, который не только дает вам сигнатуры методов, но и ключевые слова для class
, role
и т.д. Частная причина для сутенерства здесь заключается в том, что благодаря поддержке "нескольких методов" вы даже можете создать метод класса и метод объекта с тем же именем, что и каждый другой!
use Moops;
class Foo
{
multi method xxx (ClassName $class: Int $x) {
say "CLASS METHOD - value $x";
}
multi method xxx (Object $self: Int $x) {
say "OBJECT METHOD - value $x";
}
}
Foo->xxx(1);
my $foo = Foo->new;
$foo->xxx(2);