首页 文章

如何在Perl 6中重新对象?

提问于
浏览
7

另一个问题可能是“我如何继承内置类型?” .

我真的有两个问题,但它们都与我正在玩的一样 .

首先,当我想进一步限制它时,我可以创建一个类型的子集 . 我用 MyInt 做到了,它接受任何 Int . 我通过 MyInt 声明一个变量并分配给它,但当我检查它的名字时,我得到了 Int . 那么,那是什么呢?

subset MyInt where * ~~ Int;

my MyInt $b = 137;
put 'Name: ', $b.^name;  # Int, but why not MyInt?

但是,我真正想要的是一个名为 MyInt 的类,它做同样的事情 . 我可能想要添加方法

class MyInt is Int {}   # empty subclass

my MyInt $b = 137;
put 'Name: ', $b.^name;

这看起来几乎可行,但我收到一个错误:

Type check failed in assignment to $b; expected MyInt but got Int (137)

我明白为什么我在使用 subset 时没有得到同样的错误 . 这是问题1.5 .

我真正喜欢的是分配137以在分配时自动将其自身转换为 MyInt . 我知道我可以显式地构造它,但是有点烦人的是,父类仍然把它变成 Int 而不是使用更多派生类型的类型:

class MyInt is Int {}   # empty subclass

my MyInt $b = MyInt.new: 137;  # Still an Int
put 'Name: ', $b.^name;

我可以覆盖 new (直接取自Int.pm),但我对改变类型感到茫然:

class MyInt is Int {
    method new ( $value --> MyInt ) {
        my $v = callsame; # let superclass construct it
        # But, how do I make it the more specific type?
        }
    }

my MyInt $b = MyInt.new: 137;  # Still an Int
put 'Name: ', $b.^name;

我可以 bless self,但那并不认为它会,也不认为它应该 . 看着Int.pm,我看不出它是如何存储 Value 的 . 看起来它依赖于内置类型,并且可能不是传统的子类:

class MyInt is Int {
    method new ( $value --> MyInt ) {
        my $v = callsame; # let superclass construct it
        put "v is $v";
        # But, how do I make it the more specific type?
        # $v.bless (doesn't change the type, fails return type check)
        self.bless;  # doesn't retain value
        }
    }

my MyInt $b = MyInt.new: 137;  # Still an Int
put 'Name: ', $b.^name;
put 'Value: ', $b;  # 0

有一个rebless,但这不是 IntClassHow 可以链接的事物链:

class MyInt is Int {
    method new ( $value --> MyInt ) {
        my $v = callsame; # let superclass construct it
        put "v is $v";
        put "self is " ~ self.^name;
        put "HOW is " ~ self.HOW.^name;
        # No such method 'rebless' for invocant
        # $v.rebless: self.^name;
        $v.HOW.rebless: self.^name;
        }
    }

my MyInt $b = MyInt.new: 137;  # Still an Int
put 'Name: ', $b.^name;
put 'Value: ', $b;  # 0

1 回答

  • 3

    这是一个可能的解决方案:

    class MyInt is Int { };
    my $x = 42;
    Metamodel::Primitives.rebless: $x, MyInt;
    dd $x;
    

    哪个产生:

    MyInt $x = 42
    

    可能有一种更干净的方式来做你想要的,但我不知道它是什么 .

相关问题