Perlでは、オブジェクトは標準データ構造(配列、ハッシュ、スカラー)への参照を「blessing」することで実現されています。歴史的に、PerlにおけるOOPは、属性名をキー、実データを値とするハッシュへのアクセスに基づいています。このアプローチは柔軟性を提供しますが、規律を必要とします: 言語は厳密なカプセル化やアクセス修飾子を実装していないため、すべては合意に基づいています。
問題: 明示的な制約がないため、属性へのアクセスは任意のコードから可能です。オブジェクトの不変条件が容易に破壊され、名前空間が混同され、継承において誤りが生じる可能性があります。
解決策: 合意を厳格に守ること: 内部データを合意(例えば、アンダースコア)を通じて隠すこと、可能な限りアクセサメソッドを使用すること、複雑なタスクには標準モジュール(Moose、Moo、Class::Accessorなど)を使用すること。
コード例:
package Animal; sub new { my $class = shift; my $self = { _name => shift }; bless $self, $class; return $self; } sub get_name { $_[0]->{_name} } package Dog; use parent 'Animal'; sub bark { print "Woof! "; } my $dog = Dog->new("Buddy"); print $dog->get_name; $dog->bark;
主な特徴:
blessを使用せずにPerlオブジェクトを作成できますか?
回答: いいえ、blessのみが通常の参照を「->」メソッド理解可能なオブジェクトに変換します。
base/parentは何のためにあり、@ISAとの違いは何ですか?
回答: @ISAは基本クラスを指す配列です。base/parentは@ISAの操作を自動化し、モジュールの継承をより安全にします: 二重継承を防ぎ、追加のチェックを提供します。
子クラスが親クラスのメソッドを同じ名前で定義した場合、それをオーバーライドしますか?
回答: はい、子クラスで同じ名前のメソッドが定義されている場合、'->'は最初にそれを選択します — 伝統的な「メソッドオーバーライディング」が機能します。
Animalモジュールではデータが公開属性に格納され、直接アクセスされています。誰かが無意識に外部からフィールドの値を変更すると、オブジェクトは不正状態になります。
利点:
欠点:
モジュールはアクセサを使用し、すべての内部フィールドは_から始まり、明確な仕様があり—データ操作はget/setメソッドを通じて行われ、setにはチェックが入れられています。
利点:
欠点: