我想创建一个Julia类型,其中包含彼此具有固定关系的字段。为了说明,考虑一个Point类型,它表示2维中的点,并且具有表示其笛卡尔(x,y)和极坐标(r,theta)坐标的字段。这些字段必须与r * cos(theta)= x和r * sin(theta)= y相关,并且您应该能够通过指定任一组坐标来构造Point。问题是:为这种类型构建一个构造函数的好方法是什么?
答案 0 :(得分:4)
如果您乐意介绍' sub'类型,那么您可以执行以下操作:
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
另外,关于克里斯'注释,一种充分利用两个世界的方法,就是创建一个闭包生成函数,而不是一个简单的转换函数,这样一旦它被初始化它就会保留状态并且可以用来返回转换为极性的no。成本。
答案 1 :(得分: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
类型在构造之后强制执行它们。