2016-10-20 11 views
4

タイプがAbstractTで、サブタイプごとにコンストラクタT(x::Tuple)を定義したいが、一般的な方法を見つけることができない。これはJuliaのすべてがディスパッチを使用するためですコンストラクタの名前が型にマッチするので、コンストラクタにディスパッチできません。したがって、各コンストラクタは異なる関数です。そこ抽象タイプのサブタイプの汎用コンストラクタ

construct{T<:AbstractT}(::Type{T},x::Tuple) = # Define all the constructors 

だったと私は内部的にそれを行うが、それは直接T(X)を呼び出し、エラーになる他のパッケージとうまく動作しない場合、すなわちそれが働くだろう。ジュリアは私が利用できる何らかの方法でフードの下での派遣を使用していますか?

答えて

6

ちょっと面白いですが、実際には機能自体にディスパッチすることができます。コンストラクタの場合は、関数が問題になっているタイプです:

​​

あなたも、型パラメータを使用することができます...彼らは、関数名と引数リストの間の正常な場所に行くので、それは逆方向に少し見えますしかし、それだけで正常に動作します:

julia> (::Type{ConcreteT{T}}){T<:Number}() = 3 
     (::Type{ConcreteT{T}}){T<:AbstractArray}() = 4 

julia> ConcreteT{Float32}() 
3 

julia> ConcreteT{UnitRange{Int}}() 
4 

あなたも、あなたの抽象型でこれを行うが、気を付けることができます。

julia> (::Type{T}){T<:AbstractT}() = 5 

julia> ConcreteT{String}() 
ConcreteT{String}() 

julia> AbstractT() 
5 

をための抽象コンストラクタ仕事しなかった理由? ...ジュリアはあなたのためのコンストラクタを作成したことを思い出してください、これはただ派遣されているので、それらのコンストラクタは、より具体的であり、優先されます:

julia> methods(ConcreteT{String}) 
# 3 methods for generic function "(::Type)": 
(::Type{ConcreteT{T}}){T}() at REPL[1]:2 
(::Type{T}){T<:AbstractT}() at REPL[8]:1 
(::Type{T}){T}(arg) at sysimg.jl:53 

だから、あなたは、この機能を使用する場合は注意する必要があります。それはあなたの葉のコンストラクタと衝突しない場合にのみ動作します:

julia> (::Type{T}){T<:AbstractT}(x) = x 

julia> ConcreteT{String}(6) 
6 

julia> ConcreteT{Int}(7) 
7 
+0

'AbstractT()'を実行したときに何を作成しましたか?抽象型をインスタンス化できないと思った。また、 '{T <:AbstractT}'を 'AbstractT'の* concrete *子孫にマッチさせることは可能ですか? – becko

+1

コンストラクタは単なる名前の型である関数です。彼らは通常、その型のインスタンスを返しますが、これは非常に強力な規約ですが、厳密には必要ではありません。私は 'AbstractT()'が 'AbstractT()'の_some_サブタイプを返すことを期待していますが、この愚かな例では実際に整数 '5'を返しました。 –

+0

*コンクリート*タイプにのみ一致する方法はありますか? – becko

関連する問題