2016-04-18 8 views
0

下に私の問題を説明しようとするプレイグラウンドがあります。私はいくつかのオーバーロードされたジェネリックメソッド(bar<T>())を持つクラス(Foo)を持っていますが、戻り値の型はジェネリックパラメータに依存します。もう一つは、この特定の型のインスタンスのArrayを返さなければなりませんSwiftのジェネリック関数をオーバーロードするときの "Ambiguosの使用"

  • (それがBaseClassと呼ばれる下の例では)一つは、特定のタイプのサブクラスを返す必要があります
  • :私は3つの方法があります。
  • 他の2つの条件が満たされない場合は、最後のものをデフォルトのものとして使用する必要があります。

このメソッドを呼び出すと問題が発生します。私が期待しているタイプはコンパイラに伝えても、それは私にエラーのAmbiguosのbar()の使用を与えます。私の意見で

import UIKit 

class BaseClass { 
    required init() {} 
} 

class Foo { 

    // 1 
    func bar<T: BaseClass>() -> T? { 
     // Just a default implementation, it should do real work inside 
     return T() 
    } 

    // 2 
    func bar<T: BaseClass>() -> [T]? { 
     // Just a default implementation, it should do real work inside 
     return [] 
    } 

    // 3 
    func bar<T>() -> T? { 
     // Just a default implementation, it should do real work inside 
     return "Test" as? T 
    } 
} 

let foo = Foo() 

// Should call "1", because it return type is BaseClass 
let baseClassObject: BaseClass? = foo.bar() 

// Should call "2", because it return type is [BaseClass] 
let baseClasArray: [BaseClass]? = foo.bar() 

// Should call "3", because it return type is neither BaseClass nor [BaseClass] 
let anyOtherObject: String = foo.bar() 

私は右、戻り値の型、それを言っています原因は、コンパイラは、どのようなメソッド呼び出しを知っている必要がありますか?これはジェネリックスの制限ですか、何か不足していますか?

ありがとうございます。

更新4月19日

彼らは「BaseClassのは」BaseClassとしてもTとして解釈することができるため、競合が来ると言う答えで。しかし、この変更された遊び場では、コンパイラはどのメソッドが適切に使用されているかを推測します。違いはありますか?私はここで同じ競合?:< T>はまた、型BaseClassののと[BaseClassの]タイプのものであってもよいので、これは他の機能

import UIKit 

class BaseClass { 
    required init() {} 
} 

class Foo { 

    // 1 
    func bar<T: BaseClass>(param: T) -> String { 
     return "I am BaseClass" 
    } 

    // 2 
    func bar<T: BaseClass>(param: [T]) -> String { 
     return "I am [BaseClass]" 
    } 

    // 3 
    func bar<T>(param: T) -> String { 
     return "I am other thing" 
    } 
} 

let foo = Foo() 

// It prints "I am BaseClass" 
foo.bar(BaseClass()) 

// It prints "I am [BaseClass]" 
foo.bar([BaseClass(), BaseClass()]) 

// It prints "I am another thing" 
foo.bar(NSObject()) 

答えて

2

ナンバー3つの原因が競合している必要があります。コンパイラは単に、ここで何かをスローするというインターフェースを見ており、これは特定のレベルの特定性と競合します。

+0

これを拡張するには、なぜ '' let baseClassObject:BaseClass? = foo.bar() 'は自動的に最初の' bar'を呼び出しますか? – BallpointBen

+0

はい、私は紛争が最後のものから来ることを知っています。コンパイラは、戻り値の型のために最初のものを呼び出すことを知っていると思います。私は、コンパイラがより具体的ではなくより具体的であることを確認し、より具体的なものを使用すると考えました。少なくとも、それは他の場合にこのようにします。してください、@ PEEJWEEJ、私の質問の更新を参照してください。 – manueGE

関連する問題