Perl类方法和对象方法

Jac*_*kXu 12 perl class object

在学习其他语言时,类方法和对象方法之间通常存在差异.

我知道,在Perl中,班级很弱.类方法和对象方法之间是否也有区别?

我知道最常用的类方法可能是类的new方法.在Perl中,我可以使用包名称调用所有方法,但不能调用包的对象.这是为什么?

Tim*_*rce 12

perlobj手册页是有帮助的位置:

当您调用方法时,箭头左侧的东西将作为方法的第一个参数传递.这意味着当我们调用时Critter->new(),该new()方法接收字符串"Critter"作为其第一个参数.当我们调用时$fred->speak(),$fred变量作为第一个参数传递给speak().

换句话说,Perl没有在类方法和实例方法之间做出明确的区分.它们通过作为方法的第一个参数传递的内容来区分,并且如果某些方法实际上没有关心作为第一个参数传递的内容,那么你可以欺骗并称它们为"错误"的方式.

Perl不在乎.它通常不会.

  • 此外,*"Perl没有在类方法和实例方法之间做出明显的区分"*是无稽之谈.正如你的下一句话所说的那样,*"它们被作为方法的第一个参数传递的内容区分"*,但*在*方法被调用之前,Perl必须确定适当的类.这是一个字符串,例如`String-> method`,或者是一个有福的引用,比如`$ instance-> method`.如果你写'$ var ='Class'; $ var-> method`然后你调用一个类方法.如果你写`$ var = []; 祝福$ var,'Class'然后你正在调用一个实例方法. (2认同)

tob*_*ink 5

@ 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
Run Code Online (Sandbox Code Playgroud)

我要皮条客我自己对这种事情的解决方案- 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);
Run Code Online (Sandbox Code Playgroud)