另一个问题可能是"我如何从内置类型继承?".
我真的有两个问题,但它们都来自我正在玩的同一件事.
首先,当我想进一步约束它时,我可以创建一个类型的子集.我这样做,MyInt
接受任何东西Int
.我声明了一个变量来MyInt
分配给它,但当我检查它的名字时,我得到了Int
.那么,那是什么呢?
subset MyInt where * ~~ Int;
my MyInt $b = 137;
put 'Name: ', $b.^name; # Int, but why not MyInt?
Run Code Online (Sandbox Code Playgroud)
但是,我真正想要的是一个名为MyInt
同一个类的类.我可能想要添加方法
class MyInt is Int {} # empty subclass
my MyInt $b = 137;
put 'Name: ', $b.^name;
Run Code Online (Sandbox Code Playgroud)
这看起来几乎可行,但我收到一个错误:
Type check failed in assignment to $b; expected MyInt but got Int (137)
Run Code Online (Sandbox Code Playgroud)
我理解它在说什么,但不明白为什么我使用时没有得到同样的错误subset
.这是问题1.5.
我真正喜欢的是分配137以在分配时自动将其转换为a MyInt
.我知道我可以显式地构造它,但是有点烦人的是,父类仍然把它变成了一个Int
而不是使用更多派生类型的类型:
class MyInt is Int {} # empty subclass
my MyInt $b = MyInt.new: 137; # Still an Int
put 'Name: ', $b.^name;
Run Code Online (Sandbox Code Playgroud)
我可以覆盖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;
Run Code Online (Sandbox Code Playgroud)
我可以bless
自我,但这并没有保留价值(我认为它不会,也不认为它应该.看着Int.pm,我看不出它是如何存储价值的.它看起来像它依赖于内置类型,可能不是传统的子类:
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
Run Code Online (Sandbox Code Playgroud)
有一个rebless,但这并不是事情可用的编缉到链的一部分Int
或ClassHow
:
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
Run Code Online (Sandbox Code Playgroud)
这是一个可能的解决方案:
class MyInt is Int { };
my $x = 42;
Metamodel::Primitives.rebless: $x, MyInt;
dd $x;
Run Code Online (Sandbox Code Playgroud)
其产生:
MyInt $x = 42
Run Code Online (Sandbox Code Playgroud)
可能有一种更干净的方式来做你想做的事,但我不知道它是什么。
重要更新请参阅Raku rebless 不再适用于继承类。