2012-10-26 40 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