[英]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.