Метод класса и метод класса 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);