我正在研究大学问题(在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";
答案 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;
my $obj = new ClassName(...); # DO NOT USE
请参见this post和this 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 strict
和use warnings
Class->new
使用new Class
snake_case
比camelCase
has
的重复性远不如编写自己的所有getter和setter方法foo()
和get_foo()
方法相比,程序员更倾向于使用一种方法(set_foo()
既可以用作获取方法,也可以用作设置方法。