接受列表并创建对象的Perl模块

时间:2018-06-20 22:34:15

标签: perl oop module package

我正在研究大学问题(在Perl中)。我们正在创建模块,我需要编写一个简单的模块,该模块“具有获取/设置四个属性的方法:姓,名,全名以及也是人对象的孩子的列表”。

我认为我很失望,但也是把人扔给我的孩子的名单。我猜模块需要接受一个列表,然后创建一个对象列表? Python是我的核心语言,因此这一语言使我感到困惑。 get / set方法工作正常。有什么想法吗?

我的模块在这里...

#!/usr/bin/perl

package Person;

sub new
{
    my $class = shift;
    my $self = {
        _firstName => shift,
        _lastName  => shift,
    };
    bless $self, $class;
    return $self;
}
sub setFirstName {
    my ( $self, $firstName ) = @_;
    $self->{_firstName} = $firstName if defined($firstName);
    return $self->{_firstName};
}

sub getFirstName {
    my( $self ) = @_;
    return $self->{_firstName};
}

sub setLastName {
    my ( $self, $lastName ) = @_;
    $self->{_lastName} = $lastName if defined($lastName);
    return $self->{_lastName};
}

sub getLastName {
    my( $self ) = @_;
    return $self->{_lastName};
}

sub getFullName {
    my( $self ) = @_;
    return $self->{_lastName}.",".$self->{_firstName};
}

1;

我的代码在这里.....

#!/usr/bin/perl

use Person;

$object = new Person("Elvis","Presley");
# Get first name which is set using constructor.
$firstName = $object->getFirstName();
$lastName = $object->getLastName();
$fullname = $object->getFullName();

print "(Getting) First Name is : $firstName\n";
print "(Getting) Last Name is: $lastName\n";
print "(Getting) Full Name is: $fullname\n";

3 个答案:

答案 0 :(得分:6)

只需使用设置器中的对象列表即可:

#! /usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

{   package Person;

    sub new {
        my $class = shift;
        my $self = {
            _firstName => shift,
            _lastName  => shift,
            _children => [],
        };
        return bless $self, $class
    }

    sub setFirstName {
        my ($self, $firstName) = @_;
        $self->{_firstName} = $firstName if defined $firstName;
        return $self->{_firstName}
    }

    sub getFirstName {
        my ($self) = @_;
        return $self->{_firstName}
    }

    sub setLastName {
        my ($self, $lastName) = @_;
        $self->{_lastName} = $lastName if defined $lastName;
        return $self->{_lastName}
    }

    sub getLastName {
        my ($self) = @_;
        return $self->{_lastName}
    }

    sub getFullName {
        my ($self) = @_;
        return $self->{_lastName} . ', ' . $self->{_firstName}
    }

    sub getChildren {
        my ($self) = @_;
        return @{ $self->{_children} }
    }

    sub setChildren {
        my ($self, @children) = @_;
        $self->{_children} = [ @children ];
    }

}

my $object = 'Person'->new('Elvis', 'Presley');

# Get first name which is set using constructor.
my $firstName = $object->getFirstName;
my $lastName = $object->getLastName;
my $fullname = $object->getFullName;

$object->setChildren('Person'->new('Lisa', 'Presley'),
                     'Person'->new('Deborah', 'Presley'));

say "(Getting) First Name is: $firstName";
say "(Getting) Last Name is: $lastName";
say "(Getting) Full Name is: $fullname";

say "Children: ";
say $_->getFullName for $object->getChildren;

请注意,有一些模块可以简化建筑对象,例如Moo

#! /usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

{   package Person;
    use Moo;

    has first_name => (is => 'ro');
    has last_name => (is => 'ro');
    has full_name => (is => 'lazy');
    has _children => (is => 'ro',
                      init_arg => undef,
                      default => sub { [] });

    sub _build_full_name {
        my ($self) = @_;
        return $self->last_name . ', ' . $self->first_name
    }

    sub add_child {
        my ($self, $child) = @_;
        push @{ $self->_children }, $child
    }

    sub children {
        my ($self) = @_;
        return @{ $self->_children }
    }

}

my $object = 'Person'->new(first_name => 'Elvis',
                           last_name  => 'Presley');

# Get first name which is set using constructor.
my $firstName = $object->first_name;
my $lastName = $object->last_name;
my $fullname = $object->full_name;

$object->add_child($_) for 'Person'->new(first_name => 'Lisa',
                                         last_name => 'Presley'),
                           'Person'->new(first_name => 'Deborah',
                                         last_name => 'Presley');

say "(Getting) First Name is: $firstName";
say "(Getting) Last Name is: $lastName";
say "(Getting) Full Name is: $fullname";

say "Children: ";
say $_->full_name for $object->children;

答案 1 :(得分:5)

该要求意味着应该有一个可以容纳对象集合的属性,因此是对数组的引用。这是在构造函数中定义的

sub new
{
    my $class = shift;
    my $self = {
        _firstName => shift,
        _lastName  => shift,
        _children  => [ @_ ],
    };
    bless $self, $class;
    return $self;
}

其中[ ]创建一个匿名数组并返回其引用,该引用是一个标量,因此可以用于哈希值。其中的@_包含对类和名称进行Person编辑之后的其余可选参数(shift对象)。

需要检查参数,但是当在位置上使用它们时,使用普通列表会很困难。相反,请考虑使用named parameters,即。将hash(ref)传递给构造函数,通过它可以更容易地检查提供或未提供哪些参数。

接下来,您需要一种将子级添加到此属性的方法,例如

sub add_children {
    my ($self, @children) = @_;             # add checks for what's passed in
    push @{$self->{_children}}, @children;
    return $self;                           # for chaining, if desired
}

最后,当您调用此方法时,将类Person的对象传递给它

use warnings;
use strict;

use Person;

my $object = Person->new('Elvis', 'Presley');

my $child = Person->new('First', 'Last');

$object->add_children( $child );

或者,如果在其余的代码中没有使用$child变量(对象)

$object->add_children( Person->new(...) );

例如,您可以添加一个子列表add_children($c1, $c2, ...),以最初填充数据结构,也可以在出现时单独添加它们。

Person个孩子的列表也可以在构造函数中使用

my $obj = Person->new('First', 'Last', $c1, $c2,...);

使用提到的命名参数可以更清楚,更灵活地将其解压缩并在构造函数中整理出来。但是,更重要的是,一旦您学习了Perl的本机OO系统,便会研究最佳的模块Moose及其轻量级的Moo

评论

  • 始终的开头始终有use warnings;use strict;

  • 请勿使用 indirect object notation

    my $obj = new ClassName(...);   # DO NOT USE
    

    请参见this postthis great example。可以使用它 来调用构造函数的事实实际上是在滥用其本来的合法用途。使用常规方法调用

    my $obj = ClassName->new(...);
    

答案 2 :(得分:3)

很高兴您的大学在教您Perl,但是让他们失望的是,他们在教您Perl OO的“经典”版本,在现实世界中,Perl中的大多数OO工作都使用Moo这样的框架或Moose

出于兴趣,我在下面包括了Person对象的Moo版本:

package Person;

use Moo;
use Types::Standard qw[Str ArrayRef Object];

has first_name => (
  is => 'rw',
  isa => Str,
  required => 1,
);

has last_name => (
  is => 'rw',
  isa => Str,
  required => 1,
);

has children => (
  is => 'rw',
  isa => ArrayRef[Object],
);

sub full_name {
  my $self = shift;

  return $self->first_name . ' ' . $self->last_name;
}

1;

这是一个简单的测试程序:

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

use Person;

my $elvis = Person->new(
  first_name => "Elvis",
  last_name  => "Presley",
  children   => [Person->new(
    first_name => 'Lisa Marie',
    last_name  => 'Presley',
  )],
);

my $first_name = $elvis->first_name;
my $last_name  = $elvis->last_name;
my $full_name  = $elvis->full_name;

say "(Getting) First Name is : $first_name";
say "(Getting) Last Name is: $last_name";
say "(Getting) Full Name is: $full_name";

say "Elvis's first child is ", $elvis->children->[0]->full_name;

一些注意事项:

  • 在代码中始终包含use strictuse warnings
  • 始终优先于Class->new使用new Class
  • Perl程序员更喜欢snake_casecamelCase
  • Moo喜欢您对对象构造函数使用命名参数
  • 声明性属性(使用has的重复性远不如编写自己的所有getter和setter方法
  • 与单独的foo()get_foo()方法相比,程序员更倾向于使用一种方法(set_foo()既可以用作获取方法,也可以用作设置方法。