为了祝福或不祝福,这是我的问题!

NiR*_*iRC 6 oop perl class bless

来自新手用户的第一篇文章.我谷歌的每一个问题似乎都把我带到了这里,我总能得到一个很好的答案,我正在寻找的东西; 所以当我开始思考Perl中祝福的使用时,这是我的第一站.

我刚刚进入Perl的OOP,就在今天阅读帖子,询问保佑的作用.我现在明白它引用一个标量/散列/数组到一个对象,"附加"它,如果你愿意的话.

在我在Perl中看到的大多数类的例子中,它们似乎没有我以前在其他语言中看到的属性......

{ package Person;
    my $property = "This is what I'm talking about :)";

    sub new { ... }
    ...
}
Run Code Online (Sandbox Code Playgroud)

所以,我创建了一个带有属性的愚蠢类,看看会发生什么.我立刻给了物业'NIL'的价值,然后'Not Nil!' 在构造函数中.使用方法LIST,我能够打印属性,正如我所料,它打印出"Not Nil!"

我的问题是,如果属性的工作方式与我预期的相同(在体内声明)那么为什么要使用保佑呢?当你可以简单地创建一个标量/散列/数组作为属性,或者创建你想要作为属性的任何引用时,有什么额外的好处?

我希望我解释了我想要问的内容,非常绿色的Perl :)

Sin*_*nür 11

好吧,这不是你在Perl中创建类的方式.

您的$property变量在包范围中定义.因此,每个类只有一个副本,而不是每个对象都有自己的副本.

有人可能会使用基于哈希的对象来实现这样一个类,如下所示:

#!/usr/bin/perl

package Person;

use strict; use warnings;

sub new {
    my $class = shift;
    my $self = {};
    bless $self => $class;

    my ($arg) = @_;
    for my $property ( qw( message ) ) {
        if ( exists $arg->{$property} ) {
            $self->$property($arg->{$property});
        }
    }
    return $self;
}

sub message {
    my $self = shift;
    return $self->{message} unless @_;
    my ($msg) = @_;
    $self->{message} = $msg;
}

package main;

my $person = Person->new({
    message => "This is what I'm talking about :)"
});

print $person->message, "\n";
Run Code Online (Sandbox Code Playgroud)

现在,这很快就会变得乏味.因此,有一些模块可以帮助您处理这个问题,并帮助您以可靠的继承方式定义类.

Class :: Accessor就是这样一个实用程序模块.

对于启动时间不是问题的程序,您应该考虑Moose.使用Moose,您可以将上面的内容写成:

#!/usr/bin/perl

package Person;

use Moose;

has 'message' => (is => 'rw', isa => 'Str');

__PACKAGE__->meta->make_immutable;
no Moose;

package main;

my $person = Person->new({
    message => "This is what I'm talking about :)"
});

print $person->message, "\n";
Run Code Online (Sandbox Code Playgroud)

你应该阅读perldoc perltootMoose :: Manual :: Unsweetened作为标准的做事方式.


Hut*_*ut8 8

在这种情况下,您对$ property所做的事情在"Person"包的范围内被声明为变量.你改变了包内部(或使用$ Person :: property的外部),并且引用它的任何对象都将看到更新的变量,因此它的行为很像"静态属性(Java)"而没有任何真正的 "私有" " 范围.按照惯例,Perl中的隐藏内容("私有"或"受保护")以下划线为前缀,但当然不会强制执行.

正如你所指出的那样,你实际上没有使用"package"关键字创建一个新类; 你可以使用没有OOP的"包".这只是创建一个单独的"命名空间".

"祝福"变量的优势,几乎总是来自我所见过的哈希引用,就是你可以拥有方法,就像任何其他OOP语言一样.只记得保佑你在新的{}子程序中返回的任何内容("new"实际上不是一个保留字;只是一个约定).当您在"对象"(像hashref这样的祝福数据结构)上调用方法时,该方法的第一个参数就是数据结构本身.所以,如果你有一个名为$ myobject的hashref,它被祝福为AwesomeClass,你在AwesomeClass中定义了一个名为doS​​omethingAwesome的方法,它需要接受一个变量,你必须"移位"@_(这是参数列表子例程,或使用$ _ [0])来访问$ myobject hashref.Python做了类似的事情,并且所有语言都以某种方式将对象引用传递给方法.(许多中的"this"关键字,另请参阅"thiscall"调用约定)

注意:我在我的时间里看到过很多Perl抨击,这只是作为程序员的几年.Perl是一个很棒的语言,由一个非常聪明的语言学家(拉里·沃尔)制作,并且有一个狂热的追随者 - 一次比Ruby更狂热,也许,但不像David Koresh那么多.Perl的工作方式与许多语言完全不同,但是如果你看一下这个网站上的代码高尔夫条目和其他语言,你可以清楚地看到很多可以用很少的Perl完成(不保证代码易读性,特别是对于新手!)

  • 如果David Koresh和Perl一样,那么将会有多种方式退出该死的化合物!还有一个以上的灭火模块. (3认同)

mob*_*mob 5

bless"对象" 的价值就是使用特定包中的方法.

package MyClass;
sub answer { my ($self)=@_; return $self->{foo} * 42; }

package main;
my $object1 = { foo => 1, bar => "\t" };
my $object2 = bless { foo => 2, bar => "\t" }, "MyClass";

$ref1 = ref $object1;        #  'HASH'
$ref2 = ref $object2;        #  'MyClass'

$answer1 = $object1->answer;     # run time error
$answer2 = $object2->answer;     # calls MyClass::answer, returns 2 * 42 = 84
Run Code Online (Sandbox Code Playgroud)