使用 Perl 的 Method::Signatures,为什么我不能在对象实例上调用方法?
Using Perl's Method::Signatures, why can't I invoke methods on an object instance?
我关注了.
现在,当我尝试调用方法 testScript
时,出现错误 global symbol $obj requires explicit package name
,并且无法调用 testScriptTwo
。
use strict;
use warnings;
package Test;
use Method::Signatures;
method new {
my $obj = bless {}, $self;
return $obj;
}
method testScript {
$obj->testScriptTwo(); # Error happens here
}
method testScriptTwo { ... }
测试脚本:
use Test;
my $class = Test->new();
$class->testScript();
如何使用 $obj 调用包本身内的方法?
改用这个:
method testScript {
$self->testScriptTwo();
}
第一个参数在变量 $self
中,而不是 $obj
您的问题似乎表明您不了解作用域的基础知识以及普通 Perl 对象的工作原理。
在 Perl 中,当您在包名称或 blessed 引用上使用 ->method
语法时,将调用该包中的子例程 method
。子例程的第一个参数是您调用 method
.
的对象
所以,如果你这样做
My::Friend->new('Alfred');
包 My::Friend
中的 new
子例程接收两个参数。 My::Friend
和 Alfred
.
在新方法中,习惯上将第一个参数称为$class
,但这完全取决于您。如果您愿意,可以使用 $basket_case
:
sub new {
my $basket_case = shift;
my $basket = shift;
my $obj = bless { name => $basket } => $basket_case;
return $obj;
}
如果您随后对返回的引用调用方法,该方法将接收所述引用作为其第一个参数,从而允许您访问存储在该引用中的数据:
sub blurb {
my $schmorp = shift;
print $schmorp->{name}, "\n";
return;
}
综合起来:
#!/usr/bin/env perl
package My::Package;
use strict;
use warnings;
sub new {
my $basket_case = shift;
my $basket = shift;
my $obj = bless { name => $basket } => $basket_case;
return $obj;
}
sub blurb {
my $schmorp = shift;
print $schmorp->{name}, "\n";
return;
}
sub derp {
my $herp = shift;
printf "%s derp derp\n", $herp->{name};
return;
}
package main;
my $x = My::Package->new('Alfred');
$x->blurb;
$x->derp;
输出:
Alfred
Alfred derp derp
您需要了解这些基础知识。在理解下面的内容之前,试图在基础之上再增加一层抽象不会让事情变得更容易。
现在,如果您使用 Method::Signatures
,按照惯例,它会将隐含的第一个参数放入 lexically scoped 变量中,默认情况下,它调用 $self
.
您可以在特定方法中覆盖该名称,在 new
中这样做可能是一个好主意,以传达它不期望对象实例的事实;取而代之的是 returns 一个新实例。
无论您在一个子程序中如何称呼该词法范围的实例变量,都不会影响它在另一个子程序中的名称。例如:
#!/usr/bin/env perl
use strict;
use warnings;
sub a_number {
my $number = int(rand(10));
return $number;
}
sub square_that_number {
my $x = shift;
return $x * $x;
}
my $bzzzt = a_number();
my $trrrp = square_that_number($bzzzt);
print $trrrp, "\n";
输出:
$ ./zt.pl
36
好的,你需要回溯一下 - 你 new
方法首先被破坏了,这表明你并不真正理解 OO perl 是怎么回事。
一个非常简单的对象如下所示:
package Foo;
sub new {
#when Foo -> new is called, then 'Foo' is passed in as the class name
my ( $class ) = @_;
#create an empty hash reference - can be anything, but $self is the convention
my $self = {};
#tell perl that $self is a 'Foo' object
bless ( $self, $class );
#return the reference to your `Foo` object
return $self;
}
sub set_name {
my ( $self, $new_name ) = @_;
$self -> {name} = $new_name;
}
sub get_name {
my ( $self ) = @_;
return $self -> {name};
}
当您在代码中调用它时:
use Foo;
my $new_instance = Foo -> new();
class 被传递到 new
方法,然后您使用 bless
创建实例化对象。
然后你可以用它 'do stuff' - 当你 'call' 使用 ->
的方法时,子例程中的 first 参数是对象引用。
所以
$new_instance -> set_name ( "myname" );
print $new_instance -> get_name();
相当于:
Foo::set_name($new_instance, "myname" );
print Foo::get_name($new_instance);
你对 $new_instance
采取行动,这是一种允许你包含代码的魔法散列。
在您了解 OO 的基础知识之前,Method::Signatures
在很大程度上是无关紧要的。但是 that 所做的是 'simply' 扩展模块中的功能,这样你就不必提取 self/class 等
默认情况下,定义为 method
的方法会自动提供 $self
。 没有 $obj
就像你用的一样。这是您 new
方法的本地变量,在该方法之外根本不存在。
我关注了
现在,当我尝试调用方法 testScript
时,出现错误 global symbol $obj requires explicit package name
,并且无法调用 testScriptTwo
。
use strict;
use warnings;
package Test;
use Method::Signatures;
method new {
my $obj = bless {}, $self;
return $obj;
}
method testScript {
$obj->testScriptTwo(); # Error happens here
}
method testScriptTwo { ... }
测试脚本:
use Test;
my $class = Test->new();
$class->testScript();
如何使用 $obj 调用包本身内的方法?
改用这个:
method testScript {
$self->testScriptTwo();
}
第一个参数在变量 $self
中,而不是 $obj
您的问题似乎表明您不了解作用域的基础知识以及普通 Perl 对象的工作原理。
在 Perl 中,当您在包名称或 blessed 引用上使用 ->method
语法时,将调用该包中的子例程 method
。子例程的第一个参数是您调用 method
.
所以,如果你这样做
My::Friend->new('Alfred');
包 My::Friend
中的 new
子例程接收两个参数。 My::Friend
和 Alfred
.
在新方法中,习惯上将第一个参数称为$class
,但这完全取决于您。如果您愿意,可以使用 $basket_case
:
sub new {
my $basket_case = shift;
my $basket = shift;
my $obj = bless { name => $basket } => $basket_case;
return $obj;
}
如果您随后对返回的引用调用方法,该方法将接收所述引用作为其第一个参数,从而允许您访问存储在该引用中的数据:
sub blurb {
my $schmorp = shift;
print $schmorp->{name}, "\n";
return;
}
综合起来:
#!/usr/bin/env perl
package My::Package;
use strict;
use warnings;
sub new {
my $basket_case = shift;
my $basket = shift;
my $obj = bless { name => $basket } => $basket_case;
return $obj;
}
sub blurb {
my $schmorp = shift;
print $schmorp->{name}, "\n";
return;
}
sub derp {
my $herp = shift;
printf "%s derp derp\n", $herp->{name};
return;
}
package main;
my $x = My::Package->new('Alfred');
$x->blurb;
$x->derp;
输出:
Alfred Alfred derp derp
您需要了解这些基础知识。在理解下面的内容之前,试图在基础之上再增加一层抽象不会让事情变得更容易。
现在,如果您使用 Method::Signatures
,按照惯例,它会将隐含的第一个参数放入 lexically scoped 变量中,默认情况下,它调用 $self
.
您可以在特定方法中覆盖该名称,在 new
中这样做可能是一个好主意,以传达它不期望对象实例的事实;取而代之的是 returns 一个新实例。
无论您在一个子程序中如何称呼该词法范围的实例变量,都不会影响它在另一个子程序中的名称。例如:
#!/usr/bin/env perl
use strict;
use warnings;
sub a_number {
my $number = int(rand(10));
return $number;
}
sub square_that_number {
my $x = shift;
return $x * $x;
}
my $bzzzt = a_number();
my $trrrp = square_that_number($bzzzt);
print $trrrp, "\n";
输出:
$ ./zt.pl 36
好的,你需要回溯一下 - 你 new
方法首先被破坏了,这表明你并不真正理解 OO perl 是怎么回事。
一个非常简单的对象如下所示:
package Foo;
sub new {
#when Foo -> new is called, then 'Foo' is passed in as the class name
my ( $class ) = @_;
#create an empty hash reference - can be anything, but $self is the convention
my $self = {};
#tell perl that $self is a 'Foo' object
bless ( $self, $class );
#return the reference to your `Foo` object
return $self;
}
sub set_name {
my ( $self, $new_name ) = @_;
$self -> {name} = $new_name;
}
sub get_name {
my ( $self ) = @_;
return $self -> {name};
}
当您在代码中调用它时:
use Foo;
my $new_instance = Foo -> new();
class 被传递到 new
方法,然后您使用 bless
创建实例化对象。
然后你可以用它 'do stuff' - 当你 'call' 使用 ->
的方法时,子例程中的 first 参数是对象引用。
所以
$new_instance -> set_name ( "myname" );
print $new_instance -> get_name();
相当于:
Foo::set_name($new_instance, "myname" );
print Foo::get_name($new_instance);
你对 $new_instance
采取行动,这是一种允许你包含代码的魔法散列。
Method::Signatures
在很大程度上是无关紧要的。但是 that 所做的是 'simply' 扩展模块中的功能,这样你就不必提取 self/class 等
默认情况下,定义为 method
的方法会自动提供 $self
。 没有 $obj
就像你用的一样。这是您 new
方法的本地变量,在该方法之外根本不存在。