2

の最後の質問では、私は多くの無関係なことを尋ねました.いくつかの質問だけに答える複数の回答を受け入れることはできません.

use 5.010;
use strict;
use warnings;

package SomeMoo;
use Moo;
has $_ => ( is => 'rw', predicate => 1) for (qw(a1 a2 nn xx));

package SomeMoose;
use Moose;
has $_ => ( is => 'rw', predicate => "has_".$_) for (qw(a1 a2 nn xx));

package main;
use Data::Dumper;
my $omoo   = SomeMoo->new(a1 => "a1val", a2 => "a2val", xx=>"xxval");
say Dumper $omoo;

# $VAR1 = bless( {
#                 'a2' => 'a2val',
#                 'a1' => 'a1val',
#                 'xx' => 'xxval'
#               }, 'SomeMoo' );

#for Moose:  
my $omoose = SomeMoose->new(a1 => "a1val", a2 => "a2val", xx=>"xxval");
say Dumper $omoose;
#as above, only blessed to package 'SomeMoose'.

#in both cases can do the next, for getting an (partial) list "attributes"
say $_ for keys (%$omoose); #or %$omoo

#anyway, in Moose i can
say "all attributes";
say $_->name for $omoose->meta->get_all_attributes();

#what prints
# all attributes
# nn
# a2
# a1
# xx

したがって、祝福されたオブジェクトは、設定された属性のみを含むオブジェクトを参照します。

質問:

  • なぜ$self参照、(したがって、%$selfconatains) 設定されている属性のみであり、すべてではありません。たとえば、nnコード例からもですか? (blessのみが を関連付ける場合、すべてのパッケージ変数が含まれていないのreferencepackageなぜ$omooですか?) そして、Moose はどこからそれを知っているのですか?)
  • Moo の場合に all_attributes を取得するには?

明らかに、私はいくつかの基本的な知識を欠いています.. :(

4

1 に答える 1

0

$self が参照するのはなぜですか (したがって、%$self は、設定されている属性のみを参照し、すべてではなく、例のコードの nn も参照しますか?) (祝福が参照をパッケージに関連付けるだけの場合、$omoo にすべてのパッケージ変数が含まれていないのはなぜですか?)そして、Moose はどこからそれを知っているのでしょうか?)

などの新しいオブジェクトを作成するたびにSomeMoo->new、2 つの部分で構成される新しい参照を作成します。最初の部分は通常はハッシュリファレンスであるデータであり、そのハッシュリファレンスはクラスである 2 番目の部分によって祝福されSomeMooます。ハッシュは、新しいオブジェクトのこのインスタンスに関連付けられたデータを格納するために使用されますが、SomeMooデータへのアクセス/操作/実行に関連付けられたメソッドを提供するクラスです。

クラス定義内で、 という関数を呼び出しますhas。この関数は、クラスを新しいメソッドで拡張します。Moo の場合、次のように書くことで貧乏人のバージョンを作成できます。

package SimpleMoo;
no strict 'refs';

sub new {bless {}, $_[0]} # very very simple constructor (oldskool)

*{__PACKAGE__."::$_"} = sub {              # fyi: __PACKAGE__ eq "SimpleMoo"
    $_[0]->{$_} = $_[1] if exists $_[1];
    return $_[0]->{$_};
} for qw(a1 a2 nn xx);

上記はすべてのメソッドを SimpleMoo クラスに追加します。これはシンボル テーブルを操作することによって行われ、おそらく Moo の機能に非常に近いものです (ただし、Moo/Moose は、クラスが継承するメタ クラスを拡張します)。さらに単純な例では、アクセサーを手動で定義する必要があります。

package SimpleMoo;

sub new {bless {}, $_[0]} # very very simple constructor (oldskool)

sub a1 {
    my ($self) = shift;
    $self->{a1} = $_[0] if exists $_[0]; # set value if provided
    return $self->{a1}; # return the value
}
sub a2 {
    my ($self) = shift;
    $self->{a2} = $_[0] if exists $_[0]; # set value if provided
    return $self->{a2}; # return the value
}
# ... copy and paste the for nn and xx ...

上記の例からわかるように、ハッシュから値を設定および取得できるメソッドを使用してクラスを拡張していますが、オブジェクトのコンストラクターの一部として暗黙的にハッシュ構造を設定していませんnew(これをやりたい) - Moo と Moose のように。

これは、のような方法でオブジェクトを検査してkeys %$omooも、キーが設定されるまでキーが表示されないことを意味します (への呼び出し->newまたは$omoo->a1("someValue").

default => undef池上が述べたように、次のようなものをステートメントに追加するhasと、オブジェクトが最初に構築されたときに Moo/Moose が値をインスタンス化します。

$selfメソッドまたはコンストラクターによって以前に設定されたキーのみを含むオブジェクトデータがどのように含まれているかがこれで説明されることを願っています。

Moo の場合に all_attributes を取得するには?

残念ながら、Moo api には、定義されたすべての属性を一覧表示する方法がないため、サポートされているソリューションを提供することはできませんが、多くの (完全ではない、非常に推奨されない) ソリューションの 1 つを提供できます。

package SimpleMoo;
use Moo;
our @attr_list;
sub my_has {push @attr_list, $_[0]; has @_}
sub get_all_attributes {@attr_list}
my_has $_ => ( is => 'rw', predicate => 1) for (qw(a1 a2 nn xx));

package main;
my $omoo = SimpleMoo->new();
say $_ for $omoo->get_all_attributes;

Moo の誰かが、Moo で使用されているメタ クラスにアクセスしてこのリストを取得するためのより良い方法を提供できると確信しています。しかし、どちらのソリューションも推奨されていないと確信しています。

最終的に、あなたは Moose と Moo を使用しています。基になるオブジェクトを検査するべきではありません。両方のモジュールは魔法 (シンボル テーブルの変更とクラスの継承、およびすべての並べ替え) を使用し、基になるオブジェクトやクラス自体に依存して、それらが持つと予想される属性とメソッド。クラスで定義されたすべての属性を一覧表示するユース ケースがある場合は、Moose を使用してメタ クラスを検査するか、手動で定義してクラスを制御します。

また、オブジェクトからの属性のリストが必要な理由についても検討する必要があります。誰かがあなたのクラスを継承した場合はどうなりますか? または、役割をミックスインすることにしましたか?これにより、オブジェクトの属性のリストを利用しようとしていたコードが壊れますか?

于 2015-04-30T12:54:16.587 に答える