[英]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 ...
您可以覆盖默认的TWEAK
或BUILD
方法来测试文件是否存在,如果不存在,则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.