如何制作一个继承与 IO::Path 相同方法的 class?

How to make a class that inherits the same methods as IO::Path?

我想在 Raku 建立一个 class。这是我目前所拥有的:

unit class Vimwiki::File;

has Str:D $.path is required where *.IO.e;

method size {
    return $.file.IO.s;
}

我想通过简单地让我的 class 继承 IO::Path 的方法来摆脱 size 方法,但我有点不知所措来完成这个。当我尝试创建新对象时,尝试 is IO::Path 会抛出错误:

$vwf = Vimwiki::File.new(path => 't/test_file.md');

Must specify a non-empty string as a path
  in block <unit> at t/01-basic.rakutest line 24

Must specify a non-empty string as a path

我总是在看别人的代码时尝试别人的代码。你的没用。 (没有 $vwf 的声明。)这立即提醒我有人没有应用 Minimal Reproducible Example 原则。

所以我做到了,不到 60 秒后:

IO::Path.new

产生同样的错误。

为什么?

doc for IO::Path.new 显示其签名:

multi method new(Str:D $path, ...

因此,IO::Pathnew 方法需要 位置 参数,即 Str。你(和我的 MRE)还没有传递一个 Str 的位置参数。因此错误消息。

当然,您已经声明了自己的 属性 $path,并传递了一个 named 参数来设置它,不幸的是,由于与名称 path 的巧合,这让您感到困惑,但这就是编程的乐趣。

下一步,拿 #1

我认为具有重复 IO::Path 的路径属性可能会导致不必要的复杂性 and/or 错误。所以我想我会拒绝它。

如果您要做的只是对文件名进行额外的检查,那么您可以这样写:

unit class Vimwiki::File is IO::Path;

method new ($path, |) { $path.IO.e ?? (callsame) !! die 'nope' }

callsame 重新分配 正在进行的例程调用(new 方法调用),使用完全相同的参数,到下一个最合适的候选人) 如果你的新的包含 callsame 没有被调用的话,它会被选择。在这种情况下,下一个候选者将是 IO::Path.

的现有 new 方法

这似乎很好开始。然后你可以添加你认为合适的其他属性和方法...

下一步,走#2

...除了the IO::Path bug you filed,这意味着你不能用正常的方式初始化属性,因为IO::Path破坏了标准的对象构造协议! :(

Liz 展示了一种解决此错误的方法。

在这个答案的早期版本中,我不仅展示而且推荐了另一种方法,即通过 handles 委托而不是普通继承。从那以后我得出结论,那是 over-complicating 的事情,因此从这个答案中删除了它。然后我读了你的问题!

所以我猜委派方法可能仍然是合适的作为错误的解决方法。因此,如果稍后 reader 想看到它的实际效果,请按照 @sdondley 的 link 了解他们的代码。但我把它从这个答案的这个(希望是最终的!著名的遗言......)版本中删除,希望当你(后来 reader)阅读这个时,你只需要做一些真正的事情简单如 take #1.