簡體   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