首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何重载Moose构造函数?

如何重载Moose构造函数?
EN

Stack Overflow用户
提问于 2010-10-23 19:33:53
回答 2查看 3.1K关注 0票数 7

很抱歉使用Java术语,但是我如何重载Moose构造函数呢?

假设我代表的是一个片段。我可以取一个起点和一个点,或者一个起点和长度,或者终点和长度。

我怎样才能考虑到这种替代的构造方法呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-10-23 20:37:43

您不需要重写newYou can supply your own BUILD

代码语言:javascript
复制
#!/usr/bin/perl

package My::Segment;

use Moose;
use namespace::autoclean;
use Carp qw( confess );

has 'start' => (is => 'ro', isa => 'Num',
    predicate => 'has_start', writer => '_set_start',
);

has 'end' => (is => 'ro', isa => 'Num',
    predicate => 'has_end', writer => '_set_end',
);

has 'length' => (is => 'ro', isa => 'Num',
    predicate => 'has_length', writer => '_set_length',
);

sub BUILD {
    my $self = shift;

    $self->has_start and $self->has_end and $self->length and do {
        return if $self->length == $self->end - $self->start;
        confess "Inconsistent start, end and length";
    };

    $self->has_start and $self->has_end and do {
        $self->_set_length($self->end - $self->start);
        return;
    };
    $self->has_start and $self->has_length and do {
        $self->_set_end($self->start + $self->length);
        return;
    };
    $self->has_end and $self->has_length and do {
        $self->_set_start($self->end - $self->length);
        return;
    };
    confess "At least two of start, end or length must be supplied";
}

__PACKAGE__->meta->make_immutable;

package main;
use YAML;

my $x = My::Segment->new(start => 0, length => 3);
my $y = My::Segment->new(start => 1, end => 4);
my $z = My::Segment->new(end => 5, length => 3);

print Dump($_) for $x, $y, $z;

my $w = My::Segment->new(start => 0, end => 0, length => 1);
票数 11
EN

Stack Overflow用户

发布于 2010-10-24 05:24:26

思南的BUILD回答可能是最明智、最直接的解决方案。正如戴夫提到的那样,使用BUILDARGS也是一个合理的解决方案。

我觉得值得一提的是,我们也可以使用类型强制。给定一个类:

代码语言:javascript
复制
class LineSegment { 
  has [qw(startX startY endX endY)] => ( 
         isa => 'Num', 
         is  => 'ro', 
         required => 1 
  );
}

您可以使用一组强制,如下所示:

代码语言:javascript
复制
class_type 'LineSegment';

subtype StartLength 
     => as Hashref 
     => where { exists $_->{startX} && $_->{startY} && $_->{length} };

subtype EndLength 
     => as Hashref 
     => where { exists $_->{endX} && $_->{endY} && $_->{length} };    

coerce LineSegment 
     => from StartLength 
     => via { my ($endX, $endY) = calc_end($_); 
              LineSegment->new(
                   startX => $_->{startX}, 
                   startY => $_->{startY},
                   endX => $endX,
                   endY => $endY,
            )};
coerce LineSegment 
     => from EndLength 
     => via { my ($startX, $startY) = calc_start($_); 
              LineSegment->new(
                   startX => $startX, 
                   startY => $startY,
                   endX => $_->{endX},
                   endY => $_->{endY},
            )};               

然后在你的代码中:

代码语言:javascript
复制
 use Moose::Util::TypeConstraints;
 find_type_constraint('LineSegment')->coerce({
       startX => $x, 
       startY => $y, 
       length => $length
 });

虽然对于这个例子来说可能有些夸大其词,但在某些情况下,强制是一种优雅的解决方案。例如,如果您有一个预先存在的LineSegment类,但您不希望向其中添加length属性(尽管BUILDARGS在那里也可以很好地工作)

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4003765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档