使用符號作為輕量級列舉
儘管 @enum
巨集對於大多數用例非常有用,但在某些用例中它可能過多。@enum
的缺點包括:
- 它建立了一種新型別
- 擴充套件有點困難
- 它具有轉換,列舉和比較等功能,在某些應用程式中可能是多餘的
在需要較輕重量的替代物的情況下,可以使用 Symbol
型別。符號是實習字串 ; 它們代表字元序列,就像字串一樣,但它們與數字唯一相關。這種獨特的關聯可實現快速符號相等比較
我們可能會再次實現 Card
型別,這次使用 Symbol
欄位:
const ranks = Set([:ace, :two, :three, :four, :five, :six, :seven, :eight, :nine,
:ten, :jack, :queen, :king])
const suits = Set([:♣, :♦, :♥, :♠])
immutable Card
rank::Symbol
suit::Symbol
function Card(r::Symbol, s::Symbol)
r in ranks || throw(ArgumentError("invalid rank: $r"))
s in suits || throw(ArgumentError("invalid suit: $s"))
new(r, s)
end
end
我們實現內部建構函式來檢查傳遞給建構函式的任何不正確的值。與使用 @enum
型別的示例不同,Symbol
s 可以包含任何字串,因此我們必須小心我們接受哪種型別的 Symbol
s。這裡注意使用短路條件運算子。
現在我們可以像我們期望的那樣構建 Card
物件:
julia> Card(:ace, :♦)
Card(:ace,:♦)
julia> Card(:nine, :♠)
Card(:nine,:♠)
julia> Card(:eleven, :♠)
ERROR: ArgumentError: invalid rank: eleven
in Card(::Symbol, ::Symbol) at ./REPL[17]:5
julia> Card(:king, :X)
ERROR: ArgumentError: invalid suit: X
in Card(::Symbol, ::Symbol) at ./REPL[17]:6
Symbol
s 的一個主要好處是它們的執行時可擴充套件性。如果在執行時,我們希望接受(例如):eleven
作為新排名,只需執行 push!(ranks, :eleven)
就足夠了。@enum
型別無法實現這種執行時可擴充套件性。