0
sub read_file {
    open("person_file", "<person_data.txt");
    my $class = shift;
    my @people;
    while (<person_file>) {
        # entries are delimited by a | character
        # format is
        # firstname|lastname|streetaddress|town|state|zipcode
        my $line = $_;
        chomp($line);
        my @broken_line = split(/\|/, $line);
        print Dumper(@broken_line);
        my $curr_person = new Person;
        $curr_person->set_first_name($broken_line[0]);
        $curr_person->set_last_name($broken_line[1]);
        $curr_person->set_street_address($broken_line[2]);
        $curr_person->set_town($broken_line[3]);
        $curr_person->set_state($broken_line[4]);
        $curr_person->set_zip_code($broken_line[5]);
        print $curr_person->get_full_name(), "\n", 
            $curr_person->get_full_address(), "\n";
        push(@people, $curr_person);

    }
    print "\n\n\n";
    foreach my $person (@people) {
        print $person->get_full_name(), "\n", $person->get_full_address(), "\n";
    }
    print Dumper(@people);
    print "\n\n\n";
    close("person_file");
    return \@people;
}

这是输出:

$VAR1 = 'K';
$VAR2 = 'M';
$VAR3 = '4th St';
$VAR4 = 'New York';
$VAR5 = 'NY';
$VAR6 = '10001';
K M
4th St
New York, NY 10001
$VAR1 = 'C';
$VAR2 = 'G';
$VAR3 = '3 Fifth Ave';
$VAR4 = 'New York';
$VAR5 = 'NY';
$VAR6 = '10003';
C G
3 Fifth Ave
New York, NY 10003



C G
3 Fifth Ave
New York, NY 10003
C G
3 Fifth Ave
New York, NY 10003
$VAR1 = bless( do{\(my $o = 'Person')}, 'Person' );
$VAR2 = bless( do{\(my $o = 'Person')}, 'Person' );

当我读取文件时,第一块输出发生在循环中。第二个是在第二个循环中,我检查数组只是为了查看是否所有变量都正确,但它们不是。所以我发现的问题是 $curr_person 不会收到新的内存位置,即使它超出了范围或被称为新的人;并将与 $people[0] 等共享内存位置,这样人们中的所有元素都将被 $curr_person 中的任何内容覆盖。

有没有办法让 $curr_person 在循环的每次迭代中获得一个新的内存位置?

谢谢

人物类:

package Person;

use strict;
use warnings;

my $first_name;
my $last_name;
my $street_address;
my $town;
my $state;
my $zip_code;
my $unique_id;

sub new
{
    my $instance = shift;
    bless \$instance, "Person";
}

这是我第一个非练习(5 行)Perl 项目,我仍在尝试理解 Perl 中 OOP 的语法。

4

2 回答 2

1

您需要的答案已经在注释中:Person 构造函数每次都必须返回相同的实例,因此@people数组中的每一项都是指向同一实例的指针,当您更新一个实例时,您将更新所有实例。

向我们展示Person::new.

后来

感谢您的代码。结果我猜错了:并不是你的构造函数每次都返回相同的实例。问题在于您的数据存储:每个不同的 Person 实例都使用相同的变量集(在my下的声明package Person;),因此正如您已经体验过的,当您更新一个时Person,您已经更新了所有变量。

查找教程或教科书,其中包含具有 get 和 set 方法的类的已完成示例,并特别注意每个实例如何设法将其数据(名字、姓氏等)与其他所有数据分开。

于 2013-08-30T19:29:39.850 回答
1

方法将调用者作为第一个参数。调用者是在对象上调用时的对象:

$person->foo(); # $_[0] is Person object

或在该类上调用时的类名(作为纯字符串):

Person->foo();  # $_[0] is "Person" string

通常的new方法如下所示:

# Usage: Person->new(first_name => "Fred", last_name => "Flintstone")
sub new {
  my ($class, %args) = @_;
  # process arguments
  bless \%args => $class;
}

第一个参数是类名。我们祝福那个类(不一定Person!),这样我们的类就可以被继承,并且new方法可以重用。

在其他方法中,我们使用对象中的字段(它只是一个特殊的 hashref)来存储数据——但不是全局或词法变量!

sub first_name {
  my $self = shift;
  if (@_) {  # if there are args
    $self->{first_name} = shift;
  }
  return $self->{first_name};
}

等等。这在你应该真正阅读的perlootut中进行了解释。

因为编写new和访问器是重复且无聊的,人们提出了智能对象框架,使对象的工作更具表现力。最重要的是Moose框架。然后我们可以写:

package Person;
use Moose;  # this is now a Moose class

# declare attributes with `has`:

has first_name => (
  is => 'rw',  # this is now a read-write attribute
)
...
has street_address => ( is => 'rw');
has town           => ( is => 'rw');
has state          => ( is => 'rw');
has zip_code       => ( is => 'rw');
...

# new is autogenerated!

# a normal method
sub get_full_address {
  my ($self) = @_;
  return sprintf "%s\n%s, %s %s",
    $self->street_address, $self->town, $self->state, $self->zip_code;
}
于 2013-08-30T22:04:49.467 回答