Raku rebless 不再适用于继承类 [英] Raku rebless doesn't work with inherited classes anymore

查看:36
本文介绍了Raku rebless 不再适用于继承类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此线程中给出的代码不再起作用:我怎样才能在 Perl 6 中为一个对象加注?

The code given in this thread doesn't work anymore: How can I rebless an object in Perl 6?

我去年写了这段代码,然后就成功了.现在没有了:

I wrote this piece of code last year, and it worked then. Now it doesn't:

class Person { ; }
class Woman is Person { ; }
my $tom = Person.new;
my $lisa = Woman.new;

say $tom.^name;  # -> Person
say $lisa.^name; # -> Woman

Metamodel::Primitives.rebless($tom, Woman);
# -> New type Woman for Person is not a mixin type

错误消息没有意义,因为它应该与继承的类一起使用.至少是这样.

The error message doesn't make sense, as it is supposed to work with inherited classes. At least it was.

文档没有帮助;https://docs.raku.org/routine/rebless

推荐答案

它应该与继承的类一起使用

it is supposed to work with inherited classes

它从来不应该是那样的将军.我设计了那个 API 并首先实现了它,它只是作为 mixin 的一个实现细节.

It never was supposed to be that general. I designed that API and implemented it in the first place, and it was only ever intended as an implementation detail of mixins.

直到最近,它才成为语言规范测试套件的一部分 - 当它成为其中的一部分时,它已经有了当前的、更具限制性的语义.出于性能原因,对它的约束很重要:当我们知道一种类型不是混合操作的目标时,我们可以将该对象的属性访问 JIT 编译为更简单的东西(我们在更改之前的每个属性访问,现在只需在 mixin 目标类型上付费).

Until very recently, it was not part of the language specification test suite - and when it did become part of it, it already had its current, more restrictive, semantics. The constraints on it are important for performance reasons: when we know a type is not one that can be the target of a mixin operation, we can JIT-compile attribute accesses on that object into something much simpler (we paid an extra conditional move on every attribute access before the change, and now only have to pay it on mixin target types).

可以通过使用 MOP 构造类来修改原始程序以使其工作.事实上,下面的程序并不完全是原始程序;为了展示如何在子类中作为匿名角色提供方法,我做了一个小调整,以避免过多的 MOP 样板.

It's possible to modify the original program to work by using the MOP to construct the class. In fact, the following isn't quite the original program; I did a small tweak for the sake of showing how one can provide methods in the subclass as an anonymous role, so as to avoid too much MOP boilerplate.

class Person { method m() { "person" } }
constant Woman = do {
    my \w = Metamodel::ClassHOW.new_type(:is_mixin, :name<Woman>);
    w.^add_parent(Person);
    w.^add_role(role { method m() { "woman" } });
    w.^compose()
}
my $tom = Person.new;
my $lisa = Woman.new;

say $tom.^name;  # -> Person
say $lisa.^name; # -> Woman

say $tom.m; # person
Metamodel::Primitives.rebless($tom, Woman);
say $tom.m; # woman

虽然这是对原始程序在语义上最直接的修复,但还有一种更短的方法:在 Person 类型对象上使用 but 运算符来生成混合类型和返回它,然后根据自己的喜好调整其名称:

While that's the most semantically direct fix to the original program, there is a shorter way: use the but operator on the Person type object to produce a mixin type and return it, and then just tweak its name to your liking:

class Person { method m() { "person" } }
constant Woman = Person but role { method m() { "woman" } }
BEGIN Woman.^set_name('Woman');

my $tom = Person.new;
my $lisa = Woman.new;

say $tom.^name;  # -> Person
say $lisa.^name; # -> Woman

say $tom.m;
Metamodel::Primitives.rebless($tom, Woman);
say $tom.m;

反正只比原来多一行.

这篇关于Raku rebless 不再适用于继承类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆