不可變型別
最簡單的複合型別是不可變型別。不可變型別的例項(如元組 )是值。它們的欄位在建立後無法更改。在許多方面,不可變型別就像 Tuple
,它具有型別本身和每個欄位的名稱。
單例型別
根據定義,複合型別包含許多更簡單的型別。在朱莉婭,這個數字可以為零; 也就是說,允許不可變型別不包含任何欄位。這與空元組 ()
相當。
為什麼這有用呢?這種不可變型別被稱為單例型別,因為它們中只有一個例子可能存在。這些型別的值稱為單值。標準庫 Base
包含許多這樣的單例型別。這是一個簡短的清單:
Void
,nothing
的型別。我們可以驗證Void.instance
(這是檢索單例型別的單例值的特殊語法)確實是nothing
。- 任何媒體型別,例如
MIME"text/plain"
,都是具有單個例項MIME("text/plain")
的單例型別。 Irrational{:π}
,Irrational{:e}
,Irrational{:φ}
和類似型別是單例型別,它們的單例例項是無理值π = 3.1415926535897...
等。- 迭代器大小特徵
Base.HasLength
,Base.HasShape
,Base.IsInfinite
和Base.SizeUnknown
都是單例型別。
Version >= 0.5.0
- 在 0.5 及更高版本中,每個函式都是單例型別的單例例項! 像任何其他單例值一樣,我們可以從
typeof(sin).instance
恢複函式sin
。
由於它們不包含任何內容,因此單例型別非常輕量級,並且編譯器可以經常對它們進行優化,以避免執行時開銷。因此,它們非常適合於特徵,特殊標記值以及人們想要專注的功能。
要定義單例型別,
julia> immutable MySingleton end
要為單例型別定義自定義列印,
julia> Base.show(io::IO, ::MySingleton) = print(io, "sing")
要訪問單例例項,
julia> MySingleton.instance
MySingleton()
通常,人們會將此指定為常數:
julia> const sing = MySingleton.instance
MySingleton()
包裝型別
如果零欄位不可變型別是有趣且有用的,那麼也許單欄位不可變型別甚至更有用。這些型別通常稱為包裝器型別,因為它們包裝一些底層資料,為所述資料提供備用介面。Base
中包裝型別的一個例子是 String
。我們將定義一個類似於 String
的型別,命名為 MyString
。這種型別將由位元組的向量(一維陣列 )支援(UInt8
)。
首先,型別定義本身和一些自定義顯示:
immutable MyString <: AbstractString
data::Vector{UInt8}
end
function Base.show(io::IO, s::MyString)
print(io, "MyString: ")
write(io, s.data)
return
end
現在我們的 MyString
型已經可以使用了! 我們可以為它提供一些原始的 UTF-8 資料,並按我們喜歡的方式顯示:
julia> MyString([0x48,0x65,0x6c,0x6c,0x6f,0x2c,0x20,0x57,0x6f,0x72,0x6c,0x64,0x21])
MyString: Hello, World!
顯然,這種字串型別在變得像 Base.String
型別一樣可用之前需要做很多工作。
真正的複合型別
也許最常見的是,許多不可變型別包含多個欄位。一個例子是標準庫 Rational{T}
型別,它包含兩個 fieds:分子的 num
欄位和分母的 den
欄位。模擬這種型別的設計相當簡單:
immutable MyRational{T}
num::T
den::T
MyRational(n, d) = (g = gcd(n, d); new(n÷g, d÷g))
end
MyRational{T}(n::T, d::T) = MyRational{T}(n, d)
我們已成功實現了一個簡化有理數的建構函式:
julia> MyRational(10, 6)
MyRational{Int64}(5,3)