次の「設計上の問題」に対する答えは、stackoverflow と Julia ドキュメントの両方で見つけることができませんでした。
次のようなオブジェクトを定義したいとします
struct Person
birthplace::String
age::Int
end
は不変なので、誰も作成したをPerson
変更できないのは嬉しいことですが、それはまた、時間が経つと、私も変更できなくなることを意味します...birthplace
Person
age
一方、型をPerson
次のように定義すると
mutable struct Person
birthplace::String
age::Int
end
今では を作成できますage
が、 で以前持っていた安全性はなくbirthplace
、誰でもアクセスして変更することができます。
これまでに見つけた回避策は次のとおりです
struct Person
birthplace::String
age::Vector{Int}
end
ここで、 は明らかにage
1 要素ですVector
。
このソリューションは非常に見苦しく、毎回角括弧で年齢にアクセスする必要があるため、明らかに最適ではないと思います。
オブジェクト内に不変フィールドと可変フィールドの両方を持つ、よりエレガントな方法は他にありますか?
おそらく問題は、 内ですべてを可変または不変にすることの真の価値を私が見逃していることですstruct
。もしそうなら、それを説明していただけますか?
ベストアンサー1
この特定の例では、生年月日も不変であり、その情報から年齢を計算するのは簡単なので、年齢よりも生年月日を保存する方が適切と思われますが、これは単なる例に過ぎないかもしれません。
この解決策は、毎回角括弧を使って年齢にアクセスする必要があるため、かなり見苦しく、明らかに最適ではないと思います。
age(p::Person) = p.age[1]
通常、フィールドに直接アクセスする代わりに、ゲッター、つまり使用するものを定義します。これにより、括弧による「醜さ」を回避できます。
Ref
この場合、単一の値のみを格納したいので、次のように (または 0 次元のArray
)を使用することもできます。
struct Person
birthplace::String
age::Base.RefValue{Int}
end
Person(b::String, age::Int) = Person(b, Ref(age))
age(p::Person) = p.age[]
使用法:
julia> p = Person("earth", 20)
Person("earth", 20)
julia> age(p)
20