# Julia 构造函数

2018-08-12 21:25 更新

## 构造函数

``````type Foo
bar
baz
end

julia> foo = Foo(1,2)
Foo(1,2)

julia> foo.bar
1

julia> foo.baz
2``````

[1] :关于命名：尽管“构造函数”通常被用来描述创建新对象的函数，它也经常被滥用于特定的构造方法。通常情况下，可以很容易地从上下文推断出到底是“构造函数”还是“构造方法”。

## 外部构造方法

``````Foo(x) = Foo(x,x)

julia> Foo(1)
Foo(1,1)``````

``````Foo() = Foo(0)

julia> Foo()
Foo(0,0)``````

## 内部构造方法

1. 它在类型声明块内部被声明，而不是像普通方法一样在外部被声明
2. 它调用本地已存在的 `new` 函数，来构造声明块的类型的对象

``````type OrderedPair
x::Real
y::Real

OrderedPair(x,y) = x > y ? error("out of order") : new(x,y)
end``````

``````julia> OrderedPair(1,2)
OrderedPair(1,2)

julia> OrderedPair(2,1)
ERROR: out of order
in OrderedPair at none:5``````

``````type Foo
bar
baz

Foo(bar,baz) = new(bar,baz)
end``````

``````type T1
x::Int64
end

type T2
x::Int64
T2(x) = new(x)
end

julia> T1(1)
T1(1)

julia> T2(1)
T2(1)

julia> T1(1.0)
T1(1)

julia> T2(1.0)
T2(1)``````

## 部分初始化

``````type SelfReferential
obj::SelfReferential
end``````

``b = SelfReferential(a)``

``````type SelfReferential
obj::SelfReferential

SelfReferential() = (x = new(); x.obj = x)
end``````

``````julia> x = SelfReferential();

julia> is(x, x)
true

julia> is(x, x.obj)
true

julia> is(x, x.obj.obj)
true``````

``````julia> type Incomplete
xx
Incomplete() = new()
end

julia> z = Incomplete();``````

``````julia> z.xx

``````julia> type HasPlain
n::Int
HasPlain() = new()
end

julia> HasPlain()
HasPlain(438103441441)``````

``````type Lazy
xx

Lazy(v) = complete_me(new(), v)
end``````

## 参数化构造方法

``````julia> type Point{T<:Real}
x::T
y::T
end

## implicit T ##

julia> Point(1,2)
Point{Int64}(1,2)

julia> Point(1.0,2.5)
Point{Float64}(1.0,2.5)

julia> Point(1,2.5)
ERROR: `Point{T<:Real}` has no method matching Point{T<:Real}(::Int64, ::Float64)

## explicit T ##

julia> Point{Int64}(1,2)
Point{Int64}(1,2)

julia> Point{Int64}(1.0,2.5)
ERROR: InexactError()

julia> Point{Float64}(1.0,2.5)
Point{Float64}(1.0,2.5)

julia> Point{Float64}(1,2)
Point{Float64}(1.0,2.0)``````

``````type Point{T<:Real}
x::T
y::T

Point(x,y) = new(x,y)
end

Point{T<:Real}(x::T, y::T) = Point{T}(x,y)``````

``julia> Point(x::Int64, y::Float64) = Point(convert(Float64,x),y);``

``````julia> Point(1,2.5)
Point{Float64}(1.0,2.5)

julia> typeof(ans)
Point{Float64} (constructor with 1 method)``````

``````julia> Point(1.5,2)
ERROR: `Point{T<:Real}` has no method matching Point{T<:Real}(::Float64, ::Int64)``````

``julia> Point(x::Real, y::Real) = Point(promote(x,y)...);``

`promote` 函数将它的所有参数转换为相同类型。现在，所有的实数参数都可以正常运行：

``````julia> Point(1.5,2)
Point{Float64}(1.5,2.0)

julia> Point(1,1//2)
Point{Rational{Int64}}(1//1,1//2)

julia> Point(1.0,1//2)
Point{Float64}(1.0,0.5)``````

## 案例：分数

``````immutable Rational{T<:Integer} <: Real
num::T
den::T

function Rational(num::T, den::T)
if num == 0 && den == 0
error("invalid rational: 0//0")
end
g = gcd(den, num)
num = div(num, g)
den = div(den, g)
new(num, den)
end
end
Rational{T<:Integer}(n::T, d::T) = Rational{T}(n,d)
Rational(n::Integer, d::Integer) = Rational(promote(n,d)...)
Rational(n::Integer) = Rational(n,one(n))

//(n::Integer, d::Integer) = Rational(n,d)
//(x::Rational, y::Integer) = x.num // (x.den*y)
//(x::Integer, y::Rational) = (x*y.den) // y.num
//(x::Complex, y::Real) = complex(real(x)//y, imag(x)//y)
//(x::Real, y::Complex) = x*y'//real(y*y')

function //(x::Complex, y::Complex)
xy = x*y'
yy = real(y*y')
complex(real(xy)//yy, imag(xy)//yy)
end``````

``````julia> (1 + 2im)//(1 - 2im)
-3//5 + 4//5*im

julia> typeof(ans)
Complex{Rational{Int64}} (constructor with 1 method)

julia> ans <: Complex{Rational}
false``````

App下载