当我实际使用 ->meta 时,什么时候应该使 Moose 类不可变?

发布于 2024-10-26 19:30:19 字数 1191 浏览 2 评论 0原文

通常,我会在类末尾通过 __PACKAGE__->meta->make_immutable 在编译时完成一个类。但是,我什么时候应该使一个类在运行时将角色组合成不可变的?我是否应该这样做以获得更好的性能,或者这与 make_immutable 不兼容? make_immutable 似乎可以加快对象的实例化速度,但是实例化对象后它会执行任何操作吗?

例如,以下内容:

BUILD {
  my $self = shift;
  use Module::Load;

  ### Use the arguments passed in to determine roles applicable to 
  ### this instance of the object. Load and apply roles.
  for my $role ($self->_determine_roles()) { 
    load $role;
    $role->meta->apply($self);
  }

  ### $self is now a Class::MOP::Class::__ANON__... anonymous class
  ### Should I then be saying I'm done mutating it with something like this?
  ### can make_immutable even be run on an object instance and not a package?
  $self->meta->make_immutable;
}

即使上面的代码适用于单个包,当对象使用 'Foo' 角色重新祝福自己时会发生什么,导致一个匿名类,然后是第二个对象为自己祝福了一个 'Foo' (成为同一个匿名类),然后是 'Bar' 角色?当第二个对象将自己祝福到不可变的第一个匿名类中,然后尝试将角色应用于现在不可变的匿名类以创建一个新的匿名类时,它是否会正常工作?

通过阅读 Moose::Meta::Class 上的文档,看来只有类可以是不可变的,而对象的实例则不然。如果是这样,我是否应该在改变类时忽略 make_immutable

Normally I would finalize a class at compilation via __PACKAGE__->meta->make_immutable at the end of the class. However, when should I be making a class immutable that composes roles into itself at runtime? Should I even be doing so to get better performance or is this imcompatible with make_immutable? make_immutable seems to speed up instantiation of the object, but does it do anything once the object is instantiated?

For example, something along the lines of:

BUILD {
  my $self = shift;
  use Module::Load;

  ### Use the arguments passed in to determine roles applicable to 
  ### this instance of the object. Load and apply roles.
  for my $role ($self->_determine_roles()) { 
    load $role;
    $role->meta->apply($self);
  }

  ### $self is now a Class::MOP::Class::__ANON__... anonymous class
  ### Should I then be saying I'm done mutating it with something like this?
  ### can make_immutable even be run on an object instance and not a package?
  $self->meta->make_immutable;
}

Even if the code above works for a single package, what happens when a object reblesses itself with the 'Foo' role, resulting in a anonymous class, then a second object blesses itself with a 'Foo' (becoming that same anon class) then 'Bar' role? Is it going to work correctly when the second object blesses itself into the immutable first anonymous class, then tries applying the role to the now-immutable anonymous class to create a new anonymous class?

From reading the docs on Moose::Meta::Class, it appears only a class can be immutable, not instances of objects. If so, should I just be ignoring make_immutable as I am mutating my classes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

彩扇题诗 2024-11-02 19:30:19

您应该像平常一样在类的底部执行 make_immutable 操作,而不必在 BUILD 中担心它。

当您在运行时将角色应用于实例时,它不会修改实例的类来应用该角色(这将是混乱和可怕的,并且会影响该类的所有其他实例);它创建一个新的匿名类,该类继承自您的类并执行请求的角色,然后将该实例重新赋予该类。由于原始类没有被修改,因此不存在它是否开放/可变的问题。

实际上,您可以在角色应用程序之后执行$self->meta->make_immutable - 它将使新创建的匿名类保持不变 - 为了完整起见,您可能应该这样做。但它只会带来一点好处,因为 make_immutable 的大部分作用是使构造函数更快,而新类的构造函数无论如何都不会运行。

如果您想了解角色应用到实例的工作原理的详细信息,您应该查看 Moose::Meta::Role::Application::ToInstance

You should be doing make_immutable as usual at the bottom of your class, and not worrying about it at all in your BUILD.

When you apply a role to an instance at runtime it doesn't modify the instance's class to apply the role (that would be messy and horrible and affect all other instances of that class); it creates a new anonymous class that inherits from your class and does the requested roles as well, and then reblesses the instance into that class. Since the original class isn't being modified there's no issue of whether it's open/mutable or not.

You actually can do $self->meta->make_immutable after the role application — it will immutabilize the newly-created anonymous class — and for completeness you probably should. But it will only give a small benefit, since most of what make_immutable does is to make the constructor faster, and the new class's constructor doesn't run anyway.

If you want to see the details of how role application to instances works, you should peek at the source of Moose::Meta::Role::Application::ToInstance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文