Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Perl';s方法::签名,为什么可以';我调用对象实例上的方法吗?_Perl_Oop - Fatal编程技术网

使用Perl';s方法::签名,为什么可以';我调用对象实例上的方法吗?

使用Perl';s方法::签名,为什么可以';我调用对象实例上的方法吗?,perl,oop,Perl,Oop,我跟着什么 现在,当我尝试调用方法testScript时,我得到一个错误全局符号$obj需要显式的包名,它无法调用testScriptTwo use strict; use warnings; package Test; use Method::Signatures; method new { my $obj = bless {}, $self; return $obj; } method testScript { $obj->testScriptTw

我跟着什么

现在,当我尝试调用方法
testScript
时,我得到一个错误
全局符号$obj需要显式的包名
,它无法调用
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中,当您对包名或引用使用
->method
语法时,将调用该包中的子例程
method
。子例程的第一个参数是调用
方法的对象

所以,如果你这样做了

My::Friend->new('Alfred');
My::Friend
中的
new
子例程接收两个参数
My::Friend
Alfred

在一个新方法中,习惯上将第一个参数称为
$class
,但这完全取决于您。如果您愿意,您可以使用
$basket\u 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 $ ./zt.pl 36 输出:

Alfred Alfred derp derp $ ./zt.pl 36 美元/zt.pl
36好的,您需要回溯一点-您是
新的
方法首先被破坏了,这表明您并不真正了解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
创建实例化对象

然后你可以用它来“做事情”——当你使用
->
来“调用”一个方法时,子例程中的第一个参数就是对象引用

所以

相当于:

Foo::set_name($new_instance, "myname" );
print Foo::get_name($new_instance);
您可以对
$new\u instance
执行操作,这是一种允许您包含代码的神奇散列

Method::Signatures
在您了解OO的基础知识之前基本上是不相关的。但这只是“简单地”扩展模块内的函数,这样就不必提取self/class等


默认情况下,定义为
method
的方法自动提供
$self
。没有
$obj
像您正在使用的那样。这是一个对您
new
method来说是局部的变量,在它之外根本不存在

如果我想访问另一个包(父包)中的方法,该怎么办?我使用$self还是$obj?例如:
$obj->{parent}->testThree()IFAIK,始终使用
$self
$self
Method::Signatures
自动提供的功能,而不必手动完成。这就是为什么您必须理解我在我的中对非方法签名代码所做的更正。我理解,但我不理解Method::Signatures方式。我返回$obj并使用$obj创建引用,即:$obj->{parent},为什么我不能使用$obj调用其他方法并访问包中的那些引用?但是我可以在调用new()时调用它?“为什么我不能使用$obj调用其他方法…但是我可以在调用new()时调用它?”。。。因为,您不理解由子例程定义创建的词法范围。
new
中的词法变量
$obj
和您试图在
testScript
中使用的全局变量
$new
彼此无关。@SinanÜnür:我想您的意思是
全局变量$obj
,就像我说的,我理解非方法::签名方式,签名对我来说是新事物,我很难理解如何在其中使用oo。证明您并不真正理解非
方法::签名
方式。此外,如果您了解范围,您不会认为您必须在
testScript
中将实例变量命名为
$obj
,因为您在
new
中称它为
$obj
。不理解某事是不羞耻的。事实上,理解你不懂的东西是决定你是否能学到东西的最重要因素之一。