在我的last question中,我问了许多不相关的事情,并且不能接受多个答案,只回答了一些问题,所以这里显然(我希望)定义了关于(Moo)属性的问题。
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
引用,(所以%$self
只包含)
属性是什么,而不是全部,例如nn
码? (当bless
仅将reference
与package
相关联时,为什么$omoo
不包含所有包变量?)并且Moose从哪里知道它?)显然我缺少一些基本知识.. :(
答案 0 :(得分:0)
为什么$ self引用(所以%$ self conatains)只有所设置的属性,而不是全部,例如nn来自示例代码? (当祝福只将引用与包相关联时,为什么$ omoo不包含所有包变量?)并且Moose从哪里知道它?)
每次创建一个新对象(例如SomeMoo->new
)时,都会创建一个由两部分组成的新引用,第一部分是数据,通常是hashref,hashref由第二部分祝福part,即类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
或将其设置为{ {1}}。
如ikegami所述,在$omoo->a1("someValue")
语句中添加类似default => undef
的内容将导致Moo / Moose在首次构造对象时实例化该值。
我希望这能解释has
如何包含对象数据,该对象数据仅包含先前由方法或构造函数设置的键。
如何在Moo的情况下获取all_attributes?
不幸的是,Moo api没有提供列出所有已定义属性的方法,因此我无法提供支持的解决方案,但我可以提供众多(非完美的非完全推荐)解决方案中的一种:
$self
我确信Moo的某个人能够提供更好的方式来访问Moo中使用的元类来获取此列表。但我确定不推荐任何一种解决方案。
最终,你正在使用Moose和Moo,你不应该检查底层对象,两个模块都使用魔术(符号表修改和类继承,以及所有种类),你不能依赖底层对象,也不能class本身具有您期望它们具有的属性和方法。如果你有一个用例,你要列出在类上定义的每个属性,请使用Moose并检查元类,或者通过手动定义来控制你的类。
您还应该考虑为什么需要来自对象的属性列表,也许您可以自己列出它们?如果有人从你的班级继承了怎么办?或者你决定混合一个角色?这会破坏试图利用对象上的属性列表的代码吗?