jjm*_*elo 6 rakudo metamodel raku
这是做这件事的另一种尝试,本质上是创建一个冻结的类:
my class MetamodelX::Frozen is Metamodel::ClassHOW {
method compose_attributes(Mu \type) {
for self.attributes(type, :local ) -> $a {
my $attr = Attribute.new( :0rw, :0has_accessor, :name( $a.name ),
:type($a.type), :package($a.package));
self.add_attribute(type, $attr );
}
callsame();
}
}
my package EXPORTHOW {
package DECLARE {
constant frozen = MetamodelX::Frozen;
}
}
Run Code Online (Sandbox Code Playgroud)
类似于@jnthwrthngtn在这里的答案,其中方法是以特定形状创建的,以防止类如何以通常的方式创建它们,我在这里所做的是以只读方式重新创建属性,并且没有访问器,使用其余强制属性相同。然而,当您尝试实例化它时,这会失败:
Package 'Foo' already has an attribute named '$!bar'
Run Code Online (Sandbox Code Playgroud)
在任何罕见的情况下,这只会消除访问器,因为该属性已经是只读的,并且无法创建真正的冻结类(此外,它仍然可以被增强,因此不会被长期冻结)。您还能想到其他方法来实现同样的目标吗?
属性组合并不是向类中添加属性的时候;相反,它是这样的时间:
Attribute对象自行组合,这是它生成访问器、handles相关方法等的触发器我不清楚你打算实现什么,因为属性默认情况下是外部只读的,因此如果有人在rw声明的东西上定义一个错误,那么产生错误可能更有意义frozen。如果您确实想修改属性,那么您可能会更幸运地覆盖add_attribute和调整该属性此时的工作方式(例如,类似的东西method add_attribute($obj, $attr) { callwith($obj, $attr.clone(:!rw, :!has_accessor)) }可能会实现您想要的效果)。