如何创建 Str 的子类?

Ste*_*ieD 7 raku

我有这个类,它基本上是 Str 属性的包装器:

use Vimwiki::File::TextProcessingClasses;
unit class Vimwiki::File::ContentStr;

has Str $!content;

submethod BUILD( :$content ) {
    $!content = $content;
}

method gist {
    return $!content;
}

method capitalize-headers() {
    $!content = Vimwiki::File::TextProcessingClasses::HeadlineCapitalizer.new.capitalize-headers($!content);
}
Run Code Online (Sandbox Code Playgroud)

似乎用这样的东西子类化核心类会更有效Str,类似于我学到的子类化技巧IO::Path

class Blah is Str {
    method !SET-SELF() {
        self;
    }

    method new(Str:D $string) {
        self.Str::new($string)!SET-SELF();
    }    
}

my $blah = Blah.new('hello');
say $blah;

Run Code Online (Sandbox Code Playgroud)

但是,这会引发错误:Default constructor for 'Blah' only takes named arguments

Jon*_*ton 7

由于 Raku 中的构造函数是普通方法(至少如果编写正确的话),它们几乎可以工作,因此无需声明自己的构造函数。子类化Str至少是:

class SubStr is Str {
}
Run Code Online (Sandbox Code Playgroud)

我们可以验证它做了正确的事情,如下所示:

given SubStr.new(value => "hi") {
    say .WHAT;  # (SubStr) - correct type
   .say;        # hi - correct value
}
Run Code Online (Sandbox Code Playgroud)

这似乎没有特别详细的记录。

另请注意,Stris a box around the "native" str,因此如果效率问题在于内存消耗,那么您自己的围绕 a 的拳击所str消耗的不会超过Str其本身。

unit class Vimwiki::File::ContentStr;
has str $!content;
...
Run Code Online (Sandbox Code Playgroud)

  • “例如,如果我想做 `$StrSubclass.uc()`,我不想为它编写一个包装方法。” 你不知道。例如`类Str2是Str{};我的 $foo := Str2.new(value => 'string'); 说$foo.uc;# 字符串`。“我的子类 `Str` 对象是不可变的”。`Str` 对象是不可变的,因此它们的直接子类也是不可变的。因此 `"foo".=uc; ` 和 `$foo.=uc` 都会产生 `Cannot edit an immutable ... (string)`。 (2认同)