使用Perl的Method :: Signatures,为什么我不能在对象实例上调用方法?

时间:2015-02-15 12:47:53

标签: perl oop

我遵循了friedo said here

现在,当我尝试调用方法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来调用包本身内的方法?

3 个答案:

答案 0 :(得分:4)

请改用:

method testScript {
       $self->testScriptTwo();
}

第一个参数位于变量$self中,而不是$obj

答案 1 :(得分:4)

您的问题似乎表明您不了解范围的基础知识,以及普通Perl对象的工作原理。

在Perl中,当您对包名称或祝福引用使用->method语法时,将调用该包中的子例程method。子例程的第一个参数是您调用method的东西。

所以,如果你这样做

My::Friend->new('Alfred');

new中的My::Friend子例程接收两个参数。 My::FriendAlfred

在一种新方法中,习惯上将第一个参数称为$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中这样做可能是一个好主意,可以传达它不期望对象实例的事实;相反,它返回一个新实例。

无论你在一个sub中调用词法范围的实例变量,都不会影响在另一个sub中调用它的内容。例如:

#!/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

答案 2 :(得分:2)

好的,你需要回溯一下 - 你的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();

将类传递给new方法,然后使用bless创建实例化对象。

然后你可以做些什么'有了它 - 当你打电话给'使用->然后将第一个参数放入子例程的方法是对象引用。

所以

$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基本上无关紧要。但 所做的只是'简单地说'扩展模块中的功能,这样您就不必提取自我/类等。

默认情况下,定义为method的方法会自动提供$self没有 $obj喜欢你正在使用。这是一个对你new方法而言属于本地的变量,并且根本就不存在于此之外。