4

次のモジュールを作成しましたが、「最後の」ノードと「ヘッド」ノードを参照する方法がわかりません。次のノードのアドレスを前のノードの「{nextNode}」に保存するだけでなく。

クラスを保存するときにクラスの参照を保存しようとしていますが、後で「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;
}

みんなありがとう

4

3 に答える 3

6

$selfの代わりにどこにでも保存する必要があり\$classます。$ classを格納することは、オブジェクト自体ではなく、単にクラスの名前を格納することです。

また、空白の文字列$self->{nextNode}の代わりに保存します。undefまたは、さらに良いことに、それをまったく作成せず、existsそこにあるかどうかを確認するときに使用します。

于 2012-10-26T13:43:35.797 に答える
3

難しく考えすぎだよ。リストにハッシュの代わりに配列を使用する場合、 headlastについて心配する必要はありません。配列の先頭は$array[0]で、最後のメンバーは$array[-1]です。シンプルでやりやすい。

リストを定義するための簡単な標準クラス定義を次に示します。コンストラクター (新しいサブルーチン) と 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します。クラスの使用方法に関するドキュメントを見ようとすると、単語newを検索して、それがクラス オブジェクトの作成方法であることがわかります。また、変数名と を使用します。それは他の誰もがしていることなので、何が起こっているのかを知るのは簡単です.$class$self

new私のサブルーチンでは、渡された最初の項目はクラスの名前であり、他のサブルーチンに渡された最初の項目はクラス オブジェクト (つまり ) への参照であることに注意してください$self。それはおそらくクラスについて理解するのが最も難しいことです。

に注目してください。new私はすぐに my を作成し、$selfそれを祝福します。そうすれば、他のサブルーチン (メソッド) を呼び出して設定を行うことができます。このように、私のコンストラクターは私のクラスがどのように構造化されているかを知りません。これには多くの利点があります。

  • クラスを変更するとき (変更する場合ではない)、コンストラクターを変更する必要はありません。
  • コンストラクターは常にすべてのメソッドと同期しています。
  • クラスの定義を開始するときに、クラス オブジェクトがどのように構成されているかを知る必要はありません。クラスがどのように機能するかについての汚い詳細を気にすることなく、クラスを書き始めることができます。

listサブルーチン (またはメソッド) は、リストを設定するかリストを返すことができることに注意してください。同じサブルーチンを使用して値を設定または取得すると、はるかに簡単になります。メソッド サブルーチンでも、メソッド関数がエラーを返す場合は、空白の return を使用します。それ以外の場合は、常に何かを返します。これにより、メソッドが失敗したかどうかを簡単にテストできます。

おそらく必要と思われる他の方法をいくつか見てみましょう。4 つの標準リスト関数をすべて用意しましょう。

  • 押す
  • ポップ
  • シフト
  • シフト解除

次に例を示します。

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何が返ってくるのかもわかりません。私が知っているのは、プッシュが成功した場合に何かを返すということだけです。(はい、リスト内のアイテムの数を返すことは知っています)。

他の 3 つの機能はほぼ同じです。さらにいくつかの例を次に示します。

  • 現在
  • スプライス
  • 過去

currentに対して行う必要があるのは、現在の値を保存することだけです。同じ関数を使用して値を設定および取得します。私のlistメソッドまたは私のpushメソッド、または私のnewコンストラクターは、あなたがそれをどのように格納するかを知っているか、気にかけていることに注意してください。また、私たちのnextandpreviousメソッドもそうではありません。メソッド サブルーチン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;いいえ、私は単純だと言いました!)。;-)

于 2012-10-26T18:23:47.523 に答える
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
于 2012-10-28T00:27:00.063 に答える