2016-12-08 4 views
2

私は互いに固定の関係を持つフィールドを含むJulia型を作成したいと思います。説明のために、2次元の点を表し、デカルト座標(x、y)と極座標(r、theta)座標の両方を表すフィールドを持つPoint型を考えてみましょう。これらのフィールドは、r * cos(theta)= xとr * sin(theta)= yによって関連づけられなければならず、いずれの座標セットを指定してもPointを構築することができます。問題は、このタイプのコンストラクタを作る良い方法は何ですか?両方のベストを取得するにはコメント、一つの方法:あなたがご紹介させていただきます場合Juliaに関連するフィールドを持つ型を構築する

+0

ちょうどそれを一方向に格納し、他の形式の座標を与える関数を持つのはどうですか? –

+0

@ChrisRackauckas一般的に(私が与えたポイントの例よりも洗練されたタイプのために)、フィールド間の関係は計算が複雑でコストがかかるかもしれません。それを一度計算してオブジェクトに永久に関連付けておく方が良いです。 – Yly

+0

多分メモリがより大きな要件なので、それは簡単ではないので、いつものようにアプリケーションに依存します。必要な場合は、これらの関数を記述してコンストラクタで使用することができます。その問題は何ですか? –

答えて

4

また
type Cartesian 
    x::Float64; y::Float64 
end 

type Polar 
    r::Float64; t::Float64 
end 

type Point 
    x::Float64; y::Float64 
    r::Float64; t::Float64 
end 

# secondary external constructors 
Point(c::Cartesian) = Point(c.x, c.y, sqrt(c.x^2+c.y^2), atan2(c.y, c.x)) 
Point(p::Polar) = Point(p.r * cos(p.t), p.r * sin(p.t), p.r, p.t) 
Point(x::Float64, y::Float64) = Point(Cartesian(x,y)) # ... etc 

、とクリスに関してsub'typesを、あなたのような何かを行うことができます」簡単な変換関数ではなく、クロージャー生成関数を作成して、初期化した後は状態を保持し、変換を無償で極座標に戻すことができるようにすることです。ここで

3

が可能な実装です:

abstract CoordSys 
abstract Cartesian <: CoordSys 
abstract Polar <: CoordSys 

transform(r, theta, ::Type{Polar}) = r*cos(theta), r*sin(theta) 
transform(x, y, ::Type{Cartesian}) = sqrt(x^2+y^2), atan2(y, x) 

immutable Point{T<:AbstractFloat} 
    x::T 
    y::T 
    r::T 
    theta::T 
    function Point(x, y, r, theta) 
     x_ctrl, y_ctrl = transform(r, theta, Polar) 
     if isapprox(x_ctrl, x, atol = 1e-15) && isapprox(y_ctrl, y, atol = 1e-15) 
      new(x, y, r, theta) 
     else 
      error("Coordinates are inconsistent") 
     end 
    end 
end 

# These constructors take the coordinate system as an additional argument 
Point{T<:AbstractFloat}(x::T, y::T, C::Type{Cartesian}) = Point{T}(x, y, transform(x,y,C)...) 
Point{T<:AbstractFloat}(r::T, theta::T, C::Type{Polar}) = Point{T}(transform(r,theta,C)..., r, theta) 

# Convenience methods 
Point{C<:CoordSys}(x::Real, y::Real, ::Type{C}) = Point(promote(float(x), float(y))..., C) 
Point(x, y) = Point(x, y, Cartesian) 

それは建設後も、それらを強制するために建設し、immutableタイプの関係を強化するために、内部コンストラクタを使用しています。

関連する問題