2012-10-26 37 views
4

我写了下面的模块,但不知道如何引用“最后”和“头”节点。以及将下一个节点的地址存储在前一个节点的“{nextNode}”中。在Perl中实现节点列表

我试图在存储它时保存类的引用,但后来它抱怨:“List.pm中没有HASH引用”;我明白为什么但我不确定语法是怎么样的。

如果我解除引用$ head和$ last($$ last - > {nextNode} = \ $ class),那么我认为它使用了我的类的实际名称;列出而不是像我想要的以前的对象。

package List; 

my $head = undef; 
my $last = undef; 

sub new { 
    my $class = shift; 

    # init the head of the list 
    if ($head == undef) { 
    $head = \$class; 
    print "updated head to:$head", "\n"; 
    } 

    $last = \$class; 
    $last->{nextNode} = \$class; # update previous node to point on this new one  

    print "updated last to:$last", "\n"; 
    my $self = {}; 
    $self->{value} = shift;  
    $self->{nextNode} = ""; # reset next to nothing since this node is last 

    return bless $self, $class; 
} 

谢谢你们

回答

6

你应该处处存储$self代替\$class。存储$ class只是存储类的名称,而不是对象本身。

此外,对于$self->{nextNode}我会存储一个undef而不是空白字符串。或者更好的是,根本不要创建它,并在检查它是否存在时使用exists

+0

问题解决了。非常感谢!!! –

3

你在想这件事。如果你使用一个数组作为你的列表而不是哈希,你不需要担心上一个。数组的头部是$array[0],最后一个成员是$array[-1]。简单而容易。

下面是定义列表的快速标准类定义。我只定义了一个构造函数(新的子例程)和一个方法(列表)。

package Local::List; 

sub new { 
    my $class = shift; 

    my $self = {}; 
    bless $self, $class; 
    $self->list([]); 
} 

sub list { 
    my $self = shift; 
    my $list_ref = shift; 

    if (ref $list_ref ne "ARRAY) { 
     return; 
    } 
    if (defined $list_ref) { 
     $self->{LIST} = $list_ref; 
    } 
    if wantarray { 
     return $self->{LIST}; 
    } 
} 

第一件事:使用其他人使用的相同标准名称。使用new作为的构造函数。当我尝试查看关于如何使用您的课程的文档时,我可以搜索单词新的,并知道这是我创建类对象的方式。此外,使用变量名称$class$self。这就是其他人所做的,因此很容易知道发生了什么。

请注意,在我的new子例程中,传递的第一项是类的名称,而传递给其他子例程的第一项是对我的类对象(即$self)的引用。这可能是最难理解的课程。

请注意new,我立即创建我的$self并祝福它。这样,我可以打电话给我的其他子程序(我的方法)为我做设置。这样,我的构造函数不知道我的类是如何构造的。这有很多好处:

  • 当(不是如果)我修改我的类,我不必修改构造函数。
  • 我的构造函数总是与我所有的方法同步。
  • 当我开始定义类时,我不必知道我的类对象是如何构造的。我可以开始写我的课,而不用担心所有那些关于它如何工作的肮脏细节。

请注意,list子例程(或方法)可以设置列表或返回列表。如果使用相同的子例程来设置或获取该值,则更容易。同样在你的方法子程序中,当你的方法函数返回一个错误时使用一个空的返回值。否则,总是返回一些东西。这样可以很容易地测试以查看某个方法是否失败。

让我们来看看其他方法你可能想要的。让我们所有的四个标准列表功能:

  • 弹出
  • 转变
  • 不印字

下面是一个例子:

sub push { 
    my $self = shift; 
    my $member = shift; 

    if (not defined $member) { 
     return; 
    } 

    my $list_ref = $self->list; 
    my $return = push @{ $list_ref }, $member; 
    $self->list($list_ref); 

    return $return; 
} 

哇,这很简单。请注意,pop不知道我的课程是什么样子。它使用list方法来检索列表引用。然后它使用内建push方法将成员推送到列表中。我保存了返回值,这就是我将要返回的值。我什至不知道push返回。我所知道的是,如果成功,推送返回。 (是的,我知道它返回列表中的项目数量)。

其他三个功能大致相同。这里有几个:

  • 当前
  • 拼接
  • 下一个
  • 以前
  • 最后

所有你需要的当前做的是存储当前值。使用相同的功能来设置和获取值。请注意,我的list方法或我的push方法或我的new构造函数知道或关心您如何存储它。也不,我们的nextprevious方法。他们需要做的是递增或递减的current的价值和使用current方法子程序它存回:现在

sub next { 
    my $self = shift 

    my @list = $self->list; #Returns a list; 
    my $current = $self->current; 
    my $list_size = $#list; 

    if ($current eq $list_size) { 
     return; #Can't return a value after the end of the list! 
    } 

    $current++; #Increment the value; 
    my $value = $list[$current]; #I'll return this 
    $self->current($current) #Store the new current 
    return $value; 
} 

而且,你的问题的基础:获取列表的最后和头部值。这里的最后

sub last { 
    my $self = shift; 

    my $list_ref = $self->list; 
    return ${ $list_ref }[-1]; 
} 

和快速复制和粘贴会给我的头:

sub head { 
    my $self = shift; 

    my $list_ref = $self->list; 
    return ${ $list_ref }[0]; 
} 

这就是它!所有你担心的事情都是徒劳的。

对不起,很长的文章。我只是想强调一下,只要遵循一些简单的指导方针,Perl中的面向对象编程就没有那么棘手。

(简单?use Moose;怎么样不,我说简单!)。 ;-)

+1

您的解决方案非常有趣。感谢您的辛勤工作(对您而言简单);)。只是有一个问题:如果你想存储多个值,该怎么办?假设你想存储电话簿... –

+0

@YanivBenDavid电话簿作为列表成员的单个值或将电话簿存储在列表中?假设您想将电话簿存储在列表中(或者可能是电话簿条目)。我的方法中没有任何东西可以限制您存储对电话簿的引用,甚至不会更好地从电话簿类中存储电话簿对象。如果您正在讨论存储电话簿条目列表,则可以使用“Local :: List-> list”方法将整个列表设置为您的电话簿。 –

0

我只想发布我的最终工作版本的记录和您的反馈/意见。 再次感谢!

package List; 

my $head = undef; 
my $last = undef; 

sub new { 
    my ($class, $val) = @_; 
    my $self = {}; 

    # init the head of the list 
    if (!defined $head) { 
    $head = $self; 
    print "updated the head of the list ($head)" . "\n"; 
    } 
    else { 
    $last->{nextNode} = $self; # update previous node to point on this new one 
    } 

    $last = $self; # this object is now the last one 

    $self->{value} = $val; # store the value 
    $self->{nextNode} = undef; # reset next to nothing since this node is last 

    return bless $self, $class; 
} 

sub setVal { 
    my ($class, $val) = @_; 
    $class->{value} = $val; 
} 

sub getVal { 
    my $class = shift; 
    print $class->{value}; 
} 

sub getNext { 
    my $class = shift; 
    return $class->{nextNode}; 
} 

# return true if this is the last node, otherwise false. 
sub isLast { 
    my $class = shift; 
    return 1 if !defined $class->{nextNode}; 
    return 0; 
} 

sub getLast { 
    return $last; 
} 

sub getHead { 
    return $head; 
} 

# looping through all the list and printing the values 
sub showList { 
    my $node = $head; # set temp node to the head 

    while (!$node->isLast()) { 
    print $node->{value} . "\n"; 
    $node = $node->{nextNode}; 
    } 

    # printing last value. (should be defined but I check it just in case) 
    print $node->{value} . " (last)\n" if defined $node->{value}; 
} 

1; 

脚本:

my $n0 = new List(4); 
my $n1 = new List(8); 
my $n2 = new List(9); 
my $n3 = new List(3); 
my $n4 = new List(1); 
my $n5 = new List(0); 
my $n6 = new List(5); 
print "\nShow list: \n"; 
$n2->showList(); # any object will print the list