祝福还是不祝福,这是我的问题!

发布于 2024-09-13 23:46:35 字数 630 浏览 1 评论 0原文

新手用户的第一篇文章。我谷歌搜索的每个问题似乎都会把我带到这里,而且我总是能得到我正在寻找的东西的很好答案;因此,当我开始思考 Perl 中祝福的用法时,这自然是我的第一站。

我刚刚接触 Perl 的 OOP,今天读了一篇文章,询问 bless 的作用。我现在明白它引用了一个标量/散列/数组到一个对象,“附加”它,如果你愿意的话。

在我在 Perl 中看到的大多数类示例中,它们似乎没有像我在其他语言中看到的那样的属性...

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

    sub new { ... }
    ...
}

因此,我创建了一个带有属性的愚蠢类来看看会发生什么。我立即给该属性赋予值“NIL”,然后“Not Nil!”在构造函数中。使用 LIST 方法,我能够打印该属性,并且正如我所料,它打印了“Not Nil!”

我的问题是,如果属性的工作原理与我预期的相同(在正文中声明),那么为什么要使用 bless 呢?当您可以简单地创建标量/散列/数组作为属性,或者创建您想要的任何引用作为属性时,拥有该引用的额外好处是什么?

我希望我能很好地解释我想要问的问题,对 Perl 非常陌生:)

first post from a newbie-user. Every question I google seems to bring me here and I always get a great answer to what I'm looking for; so naturally this was my first stop when I began pondering the usage of blessing in Perl.

I've just gotten into Perl's OOP and just today read the post asking what bless does. I now understand that it references a scalar/hash/array to an object, 'attaching' it, if you will.

In most of the examples of classes I see in Perl, they don't seem to have properties like I'm used to seeing in other languages...

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

    sub new { ... }
    ...
}

So, I created a stupid class with a property to see what would happen. I gave the property the value 'NIL' right off the bat and then 'Not Nil!' in the constructor. Using a method LIST, I was able to print the property, and as I expected, it printed 'Not Nil!'

My question is, if properties work the same as I expected them to work (declared in the body) then why use bless at all? What is the added benefit of having that reference when you could simply create a scalar/hash/array as a property, or create whatever references you want as a property?

I hope I explained what I'm trying to ask well enough, very green with Perl :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

献世佛 2024-09-20 23:46:35

嗯,这不是在 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";

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

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";

您应该阅读 perldoc perltootMoose::Manual::Unsweetened 用于标准的处理方式。

Well, that is not how you create classes in Perl.

Your $property variable is defined in package scope. Therefore, there will only one copy of it per class rather than each object having its own copy.

One might implement such a class using hash based objects the long and hard way as below:

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

Now, this gets tedious fast. So, there are modules that help you deal with this as well as helping you define your classes in way that is safe for inheritance.

Class::Accessor is one such utility module.

For programs where startup time is not an issue, you should consider Moose. With Moose, you can write the above as:

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

You should read perldoc perltoot and Moose::Manual::Unsweetened for the standard way of doing things.

意中人 2024-09-20 23:46:35

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

正如您所指出的,您实际上并没有使用“package”关键字创建一个新类;而是创建了一个新类。你可以使用“package”而不需要OOP。这只是创建一个单独的“命名空间”。

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

注意:我在担任程序员的时间里见过很多 Perl 攻击。 Perl 是一种很棒的语言,它是由一位非常聪明的语言学家(Larry Wall)创建的,并且拥有狂热的追随者——也许比 Ruby 更狂热,但不如 David Koresh)。 Perl 的工作方式与许多语言非常不同,但是如果您查看本网站和其他网站上的代码高尔夫条目,您可以清楚地看到,只需很少的 Perl 就可以完成很多工作(不能保证代码的易读性,尤其是对于新手而言!)

What you did with $property in this case is declared a variable in the "Person" package's scope. You change that inside (or outside using $Person::property) of the package, and any object that refers to it will see the updated variable, so it acts a lot like a "static attribute (Java)" without any real "private" scope. By convention, hidden things in Perl ("private" or "protected") are prefixed with an underscore, but of course this isn't enforced.

You don't actually make a new class, as you pointed out, with the "package" keyword; you can use "package" without OOP at all. That simply creates a separate "namespace".

The advantage of "blessing" a variable, almost always a hash reference from what I've seen, is that you can have methods, just like any other OOP language. Just remember to bless whatever you return in the new {} subroutine ("new" isn't actually a reserved word; just a convention). When you call a method on the "object" (a blessed data structure like a hashref), the first argument of the method is the data structure itself. So, if you have a hashref called $myobject, which is blessed to AwesomeClass, and you define a method in AwesomeClass called doSomethingAwesome, which needs to accept one variable, you would have to "shift" @_ (which is the argument list of the subroutine, or use $_[0]) to access the $myobject hashref. Python does something similar, and all languages pass the object reference to the method somehow. ("this" keyword in many, see also "thiscall" calling convention)

NB: I've seen lots Perl bashing in my time, which has only been a few years as a programmer. Perl is an awesome language that was made by a very smart linguist (Larry Wall) and has a fanatical following -- more fanatical at one time than Ruby, perhaps, but not as much as David Koresh). Perl does things very differently than lots of languages but if you look at code golf entries on this site and others, you can clearly see that much can be accomplished with very little Perl (no guarantees about code legibility, especially for newcomers!)

仄言 2024-09-20 23:46:35

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

The value of bless'ing an object is getting to use the methods from a particular package.

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
无悔心 2024-09-20 23:46:35

呃……Sinan 的回答完全不符合我的口味,至少在上午 12 点之后是这样:)

所以我会给出一个更短、更少 Perly 的答案,只是为了多样性。

据我所知,你的问题实际上并不是关于 Perl,并且可以很容易地以另一种形式表达:“当 C 已经有了结构时,为什么还要在其中使用 C++ 和 OOP?”

换句话说,您似乎在问使用 OOP 范式的意义是什么。

答案当然是它比纯过程编程更容易解​​决某些软件工程问题。强调某些 - OOP 并不是解决所有问题的灵丹妙药,任何技术/方法/范式都不是。

使用 OOP(在 Perl 中以包作为类,祝福散列作为 Perl 中的对象)可以让您享受继承、多态性和其他 OOPyish 的好处,您可能已经从非 Perl OOP 经验中相当熟悉这些好处。

你能 100% 完成使用纯数据结构的祝福对象所做的事情吗?绝对地。 100% 的代码会像使用对象一样简单/简短/可读/可维护吗?很可能不会,尽管这取决于您的 OOP 代码实际利用 OOP 提供的好处的程度(顺便说一句,我遇到过遇到过所谓的 OOP 代码(Perl 而非 Perl),但它并没有真正利用 OOP 的任何优势) OOP 范式,如果去掉了 OOP 的装饰,可能会变得更容易阅读和理解)。

Ugh... Sinan's answer is entirely too learned for my taste, at least past 12am :)

So I'll give a shorter and somewhat less Perly one, just for variety's sake.

Your question is not really about Perl as far as I can tell, and can be just as easily ased in another form: "Why bother using C++ and OOP in it when C already has structs?"

In other words, you seem to be asking what the point of using OOP paradigm is.

The answer is of course that it helps solving certain software engineering problems easier than pure procedural programming. Emphasis on certain - OOP is not a panacea for every problem, any more than ANY technique/approach/paradigm is.

Using OOP (in a form of packages as classes and blessed hashes as objects in Perl) allows you to enjoy the benefits of inheritance, polymorphism and other OOPyish mumbo-jumbo which you are probably already fairly familiar with from you non-Perl OOP experience.

Can you do 100% of what you'd have done with a blessed object with a pure data structure? Absolutely. Would 100% of it be just as easy/short/readable/maintainable code as you can achieve using objects? Most likely not, though it depends on how well your OOP code actually leverages the benefits that OOP provides (BTW, I have encountered supposedly OOP code (Perl and not) which wasn't really taking any advantage of OOP paradigm and could have been made easier to read and understand had it been stripped of its OOP chrome).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文