"compose_attributes" 显然是在组合属性之前调用的

"compose_attributes" is apparently called before attributes are composed

This is another attempt to do this thing, essentially create a frozen class:

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;
    }
}

与@jnthwrthngtn 的回答 类似,其中以特定形状创建方法以防止 Class 如何以通常的方式创建它们,我在这里所做的是重新创建以只读方式且没有访问器的属性,其余强制属性相同。但是,当您尝试实例化它时,这会失败:

Package 'Foo' already has an attribute named '$!bar'

在极少数情况下,这只会消除访问器,因为该属性已经是只读的,并且不会设法进行真正的冻结 class(此外,它仍然可以被扩充,所以不会被远射冻结)。您还能想到其他方法来实现同样的目标吗?

属性组合不是在属性添加的时候class;相反,它是:

  • 我们承诺 class 的一组特定属性,并将其传达给底层运行时(通常是 MoarVM),它计算对象的内存布局
  • 我们告诉每个 Attribute 对象自行组合,这是它生成访问器、handles 相关方法等的触发器

我不清楚你打算实现什么,因为属性在默认情况下是外部只读的,所以如果有人定义了一个 [=12],那么产生错误可能更有意义=] 一个关于声明的东西 frozen。如果你确实想修改属性,你可能会更幸运地覆盖 add_attribute 并调整属性在此时的工作方式(例如,method add_attribute($obj, $attr) { callwith($obj, $attr.clone(:!rw, :!has_accessor)) } 之类的东西可能会实现你想要的)。