繁体   English   中英

class属性约束的推荐方法?

[英]Recommended method for constraining class attributes?

我有一个带有字符串属性的 class。 该属性表示文件的路径。 我想在构建 object 之前确保此文件存在。将来,我可能还想对该文件进行额外的检查,比如它的格式是否正确。

无论如何,如果文件不存在,我想抛出一个描述性异常。

经过反复试验,我想出了这个:

unit class Vim::Configurator;
sub file-check($file) {
    die (X::IO::DoesNotExist.new(:path($file), :trying('new'))) if !$file.IO.f.Bool;
    return True;
}

has Str:D $.file is required where file-check($_);

但众所周知,有不止一种方法可以做到这一点。

另一种选择是将约束逻辑放入new方法或build方法中。 这没关系,但这感觉很老派,我想我更喜欢像第一个例子那样在属性旁边拼写出每个属性的逻辑。

第三种选择:

has Str:D $.file is required where *.IO.f.Bool == True;

这很好而且简洁,但抛出的错误非常难以理解。

第四个选项是使用subset来约束属性,如下所示:

subset Vim::Configurator::File where *.IO.f.Bool == True;

unit class Vim::Configurator;
has Vim::Configurator::File $.file is required;

此处抛出的错误消息也不是最大的。 另外,我觉得很奇怪。

我敢肯定还有其他方法可以给这只猫剥皮,我想知道其他人在做什么,以及是否有比上述任何方法更好的方法。 谢谢。

第三种选择:
has Str:D $.file is required where *.IO.f.Bool == True;
这很好而且简洁,但抛出的错误非常难以理解。

你可以在 where 子句中有一个块并在那里抛出:

class A {
    has Str:D $.file where { .IO.f orelse .throw }
}

A.new(file => "absent");

这给出了类似的东西

Failed to find 'absolute/path/to/absent' while trying to do '.f'
  in block  at ...
  in block <unit> ...

where子句中, $_为传递的文件字符串,即上面的"absent"。 然后检查它作为文件的存在; 如果找不到文件, .IO.f会失败,因此对于orelse$_将是它导致的失败,然后是.throw n。

但是,如果传递的文件字符串确实存在,但它不是文件而是目录,那么.IO.f不会失败,而是返回 False! 然后orelse不会切换到.throw因为 False 是定义的值。 在这种情况下,我们返回到一条无用的消息。 为此,我们可以先检查existence,然后单独处理fileness:

class A {
    has Str:D $.file where { .IO.e.not
                                ?? fail qq|"$_" does not exist at all|
                                !! .IO.f or fail qq|"$_" is not a file| };
}

然后

>>> A.new(file => "absent")
"absent" does not exist at all
  in block ...

>>> A.new(file => "existing_dir")
"existing_dir" is not a file
  in block ...

您可以覆盖默认的TWEAKBUILD方法来测试文件是否存在,如果不存在,则die

class File {
    has Str $.path is required;
    
    submethod BUILD(:$path) {
        die 'File $path does not exist!' unless $path.IO.e; # Check if the file corresponding to the path exists
        $!path := $path;
    }
}

如果您想要更细粒度的控制,您还可以编写一个工厂来进行检查,而不是在 class 级别上进行检查。

进一步阅读: https://docs.raku.org/language/objects#Object_construction

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM