在我的str子类中为“无法修改不可变的”工作?
我有一个子类 Str
的类:
use Vimwiki::File::TextProcessingClasses;
unit class Vimwiki::File::ContentStr is Str;
method new(Str:D $string) {
self.Str::new(value => $string);
}
# this method fails
method capitalize-headers() {
self = Vimwiki::File::TextProcessingClasses::HeadlineCapitalizer.new.capitalize-headers(self);
}
问题是 capitalize-headers
方法失败,并出现 Cannot edit an immutable
错误,因为它是一个字符串。我可以避免这个问题的一种方法是简单地不子类化 Str
并为我想使用的 Str
方法编写包装器,如下所示:
unit class Vimwiki::File::ContentStr;
has Str $!content;
method uc() {
$!content = $!content.uc;
}
但这让我想知道是否不写对于这些包装器方法,Raku 中可能存在类似于 AUTOLOAD 的功能,因此如果方法不存在,则可能会默认在 $!content
属性上调用该不存在的方法。
这可能吗?或者是否有更干净的方法来解决不可变对象问题?
I have this class which subclasses Str
:
use Vimwiki::File::TextProcessingClasses;
unit class Vimwiki::File::ContentStr is Str;
method new(Str:D $string) {
self.Str::new(value => $string);
}
# this method fails
method capitalize-headers() {
self = Vimwiki::File::TextProcessingClasses::HeadlineCapitalizer.new.capitalize-headers(self);
}
The problem is the capitalize-headers
method fails with the Cannot modify an immutable
error because it's a string. One way I could avoid this problem is to simply not subclass Str
and write wrappers for the Str
methods I want to use like this:
unit class Vimwiki::File::ContentStr;
has Str $!content;
method uc() {
$!content = $!content.uc;
}
But that got me wondering if instead of writing these wrapper method, there might be something like AUTOLOAD in Raku so that if a method does not exist, the non-existent method could default to being called on the $!content
attribute.
Is this possible? Or is there a cleaner way around the immutable object problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Str
类型是不可变的。当您编写时:它可以工作,因为
$x
是一个Scalar
容器。您没有更改Str
,只是安排$x
引用不同的Str
。 Raku 标准库中的所有地方都依赖于Str
是不可变的,因此即使您要以某种方式创建一个可变子类,您也不会过得很愉快!除此之外,
self
也始终是不可变的。您可以这样做:并按如下方式使用它:
这又是改变
Scalar
容器$x
并放置一个新的SubStr
实例将值HI
写入其中。因此:将会消亡:
因此,如果您想要一个
Str
周围的可变包装器,您实际上必须使用组合,而不是继承。这就是
FALLBACK
方法。 (还有handles
特征 ,但这并不完全是你想要的,因为我想你希望保留包装。)The
Str
type is immutable. When you write:It works because
$x
is aScalar
container. You're not changing theStr
, just arranging for$x
to refer to a differentStr
. ThatStr
is immutable is relied on all over the place in the Raku standard library, so even if you were to somehow create a mutable subclass, you're not in for a good time!Further to that
self
is also always immutable. You can do this:And use it as follows:
This is is, again, mutating the
Scalar
container$x
and putting a newSubStr
instance with the valueHI
into it. Thus this:Will die:
Thus if you want a mutable wrapper around
Str
, you'll really have to use composition, not inheritance.That's the
FALLBACK
method. (There's also thehandles
trait, but that's not quite what you want, as I imagine you wish to retain the wrapping.)好的,这是完成工作的代码:
OK, here's the code that does the job: