Perl:没有类型约束的 Class::Struct

发布于 2024-11-29 01:07:56 字数 2724 浏览 2 评论 0原文

我正在研究一些代码,其中将 coderefs 与变量捆绑在一起是有意义的,但使用完整的 OOD 则没有意义。基本上,我正在编写功能代码,但采用了一些精选的 OO 风格结构来封装状态性真正有意义的内容。除此之外,它主要是无状态函数。

使用 Moose 来做到这一点就像用自动步枪来惩罚偶尔迟到的同事一样:在多种方面完全是过度杀戮。所以别再说“所有 PERL OOP 现在都必须使用 MOOSE!!!”咒语。

因此,我跑到了好的 ol'blessed-hashref 类来执行我的命令,但发现编写访问器代码很痛苦,并且不想引入非标准模块来完成本质上非常琐碎的任务。

在浏览 http://perldoc.perl.org 上的页面后,我偶然发现了 Class::Struct 和 Object: :Accessor,是简化OO属性构造的核心模块。完美,我想。但是...

Object::Accessor 似乎是完美的门票,但我只是在构造函数中使用了它的 mk_accessor sub,这似乎不像使用编译时 Class::Struct 那样优雅,它也写了我的默认值对我来说是构造函数。总而言之,与 Object::Accessor 相比,我更喜欢 Class::Struct,因为它允许的样板代码稍微少一些,并且具有更具声明性的语法。

使用简单示例进行比较,以防您想知道:

使用 Class::Struct:

#!/usr/bin/perl

use 5.014;
use autodie;
use strict;
use warnings;

package Account {
    use Class::Struct
        first_name   => '$',
        last_name    => '$',
        age_in_years => '$',
        activated    => '$',
        ;

    sub formatted {
        my ($self_ref) = @_;
        return sprintf
            "First name:   %s\n" .
            "Last name:    %s\n" .
            "Age in Years: %d\n" .
            "Activated:    %s",
            $self_ref->first_name,
            $self_ref->last_name,
            $self_ref->age_in_years,
            $self_ref->activated || 'No'
            ;
    }
}

my $account = Account->new;

$account->first_name('Tom');
$account->last_name('Smith');
$account->age_in_years(16);
$account->activated('Yes');

say $account->formatted

使用 Object::Accessor:

use 5.014;
use autodie;
use strict;
use warnings;

package Account {
    use base 'Object::Accessor';

    sub new {
        my ($type) = @_;
        my $self = bless { }, $type;
        $self->mk_accessors(qw(first_name last_name age_in_years activated));
        return $self;
    }

    sub formatted {
        my ($self_ref) = @_;
        return sprintf
            "First name:   %s\n" .
            "Last name:    %s\n" .
            "Age in Years: %d\n" .
            "Activated:    %s",
            $self_ref->first_name,
            $self_ref->last_name,
            $self_ref->age_in_years,
            $self_ref->activated || 'No'
            ;
    }
}

my $account = Account->new;

$account->first_name('Tom');
$account->last_name('Smith');
$account->age_in_years(16);
$account->activated('Yes');

say $account->formatted;

确实,两者都是完全可以接受的,但在我看来,前者要干净得多。我想知道的是,我可以在不指定类型约束的情况下使用 Class::Struct 吗?

我在使用它们的上下文中不需要它们,但我似乎无法仅添加访问器而不指定它们旁边的类型约束。毫无疑问,我也由于不必要的类型检查而降低了性能。

如果这是不可能的,我将坚持使用 Object::Accessor。但是 Class::Struct 是否可以使用非类型约束的访问器?

I'm toying around with some code where bundling coderefs with variables makes sense, but using full blown OOD doesn't. Basically, I'm writing functional code but resorting to a select few OO-style structures to encapsulate stuff where statefulness really makes sense. Outside that it's mostly state-free functions.

Using Moose for this would be like disciplining occasionally-late coworkers with an automatic rifle: complete overkill in more ways than one. So spare me the 'ALL PERL OOP MUST USE MOOSE NOW!!!' mantra.

So I ran to the good ol' blessed-hashref class to do my bidding, but found that writing accessor code is a pain, and didn't want to pull in non-standard modules for what is essentially a very trivial task.

After shuffling through pages on http://perldoc.perl.org, I stumbled across Class::Struct and Object::Accessor, which are core modules that ease the construction of OO attributes. Perfect, I though. But...

Object::Accessor seemed like the perfect ticket, but I was simply using its mk_accessor sub in the constructor, which didn't seem anywhere near as elegant as using compile-time Class::Struct, which also wrote my default constructor for me. All in all, I preferred Class::Struct to Object::Accessor because allowed slightly less boilerplate and had a more declarative syntax.

A comparison using trivial examples, in case you're wondering:

Using Class::Struct:

#!/usr/bin/perl

use 5.014;
use autodie;
use strict;
use warnings;

package Account {
    use Class::Struct
        first_name   => '

Using Object::Accessor:

use 5.014;
use autodie;
use strict;
use warnings;

package Account {
    use base 'Object::Accessor';

    sub new {
        my ($type) = @_;
        my $self = bless { }, $type;
        $self->mk_accessors(qw(first_name last_name age_in_years activated));
        return $self;
    }

    sub formatted {
        my ($self_ref) = @_;
        return sprintf
            "First name:   %s\n" .
            "Last name:    %s\n" .
            "Age in Years: %d\n" .
            "Activated:    %s",
            $self_ref->first_name,
            $self_ref->last_name,
            $self_ref->age_in_years,
            $self_ref->activated || 'No'
            ;
    }
}

my $account = Account->new;

$account->first_name('Tom');
$account->last_name('Smith');
$account->age_in_years(16);
$account->activated('Yes');

say $account->formatted;

Really, both are perfectly acceptable, but the former is quite a bit cleaner IMO. What I want to know, is, can I use Class::Struct without specifying the type constraints?

I don't need them in the context I'm using them, yet I don't seem to be able to just add accessors without specifying type constraints alongside them. No doubt I loose performance due to unnecessary type checking too.

If this isn't possible, I'll just stick to Object::Accessor. But are non-type-constrained accessors possible with Class::Struct?

, last_name => '

Using Object::Accessor:


Really, both are perfectly acceptable, but the former is quite a bit cleaner IMO. What I want to know, is, can I use Class::Struct without specifying the type constraints?

I don't need them in the context I'm using them, yet I don't seem to be able to just add accessors without specifying type constraints alongside them. No doubt I loose performance due to unnecessary type checking too.

If this isn't possible, I'll just stick to Object::Accessor. But are non-type-constrained accessors possible with Class::Struct?

, age_in_years => '

Using Object::Accessor:


Really, both are perfectly acceptable, but the former is quite a bit cleaner IMO. What I want to know, is, can I use Class::Struct without specifying the type constraints?

I don't need them in the context I'm using them, yet I don't seem to be able to just add accessors without specifying type constraints alongside them. No doubt I loose performance due to unnecessary type checking too.

If this isn't possible, I'll just stick to Object::Accessor. But are non-type-constrained accessors possible with Class::Struct?

, activated => '

Using Object::Accessor:


Really, both are perfectly acceptable, but the former is quite a bit cleaner IMO. What I want to know, is, can I use Class::Struct without specifying the type constraints?

I don't need them in the context I'm using them, yet I don't seem to be able to just add accessors without specifying type constraints alongside them. No doubt I loose performance due to unnecessary type checking too.

If this isn't possible, I'll just stick to Object::Accessor. But are non-type-constrained accessors possible with Class::Struct?

, ; sub formatted { my ($self_ref) = @_; return sprintf "First name: %s\n" . "Last name: %s\n" . "Age in Years: %d\n" . "Activated: %s", $self_ref->first_name, $self_ref->last_name, $self_ref->age_in_years, $self_ref->activated || 'No' ; } } my $account = Account->new; $account->first_name('Tom'); $account->last_name('Smith'); $account->age_in_years(16); $account->activated('Yes'); say $account->formatted

Using Object::Accessor:

Really, both are perfectly acceptable, but the former is quite a bit cleaner IMO. What I want to know, is, can I use Class::Struct without specifying the type constraints?

I don't need them in the context I'm using them, yet I don't seem to be able to just add accessors without specifying type constraints alongside them. No doubt I loose performance due to unnecessary type checking too.

If this isn't possible, I'll just stick to Object::Accessor. But are non-type-constrained accessors possible with Class::Struct?

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

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

发布评论

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

评论(1

从﹋此江山别 2024-12-06 01:07:56

我更喜欢 Class::Struct 来完成任务。我通常只使用标量,它们没有验证,您可以向它们存储任何内容(例如 arrayref 或 hashref)。

另一个优点是您选择的语法使您的对象基于数组,数组更小并且访问速度更快。没什么戏剧性的,但如果你有很多对象,它会有所帮助。

package Account;
use Class::Struct
    map { $_ => '
 } qw(
        first_name
        last_name
        age_in_years
        activated
        items
    );

package main;

my $acc = Account->new(
    first_name => 'John',
    last_name  => 'Doe',
    items      => ['a' .. 'z']
);

I prefer Class::Struct for the task. I am usually using only scalars, they have no validation and you can store anything to them (like arrayref or hashref).

Another advantage is that syntax you've choosen is making your objects based on arrays, which are smaller and have faster access. Nothing dramatic, but if you have many objects, it can help.

package Account;
use Class::Struct
    map { $_ => '
 } qw(
        first_name
        last_name
        age_in_years
        activated
        items
    );

package main;

my $acc = Account->new(
    first_name => 'John',
    last_name  => 'Doe',
    items      => ['a' .. 'z']
);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文