2017-11-11 5 views
0

私の実際のコードでは、MyFooオブジェクトは、共有したくない実装の詳細である他のことを行います。私はそのための句が正しくタイプをマップする場所しかし、私は必要を見つけることができない、私はFooプロトコルの後ろにそれを隠すためにしようとしている:Swift Generic Constraintは値を変換できません

protocol Foo { 
    associatedtype Bar 
    func process(bar:Bar) 
} 

class MyFoo<T>: Foo { 
    func process(bar: T) {} 
} 

class Buzz<U> { 
    private let myFoo = MyFoo<U>() 

    init<BarProcessor:Foo>(block:(BarProcessor)->Void) where BarProcessor.Bar == U { 
     block(myFoo) // error: '(@lvalue MyFoo<U>) -> Void' is not convertible to '(BarProcessor) -> Void' 
    } 
} 

または私のように、ここで欠けているより多くの基本的な概念がありますなぜこれが機能していないのですか?

答えて

1

これは、あなたがそれが意味どう思うかという意味ではありません:これは特化されているプロトコルとしてBarProcessorを扱うしようとしている

init<BarProcessor:Foo>(block:(BarProcessor)->Void) where BarProcessor.Bar == U 

。しかしそれはそうではありません。 BarProcessorは具体的なタイプです。したがって、の特定の(ただし汎用)タイプを受け入れるブロックを渡しています。 MyFooをそれに渡そうとしますが、それはその特定のタイプではない可能性があります。

このようにプロトコルとジェネリックを混ぜ合わせていると、プロトコルを過度に使用している可能性があります。取り除くFoo。プロトコルは実装の詳細を隠す方法ではありません。実装の詳細を隠すツールは、アクセス制御(privateおよびinternal)です。

タイプを完全に非表示にしたい場合は、プロトコルではなくタイプ消しゴムです。例えば、(彼らは「foo」と「bar」せずに何を意味するかに物事をリネーム):

private struct MyProcessor<T> { 
    func process(element: T) {} 
} 

// Type-erases MyProcessor 
struct Processor<T> { 
    fileprivate let processor: MyProcessor<T> 
    func process(element: T) { processor.process(element: element) } 
} 

class Machine<U> { 
    private let myProcessor = MyProcessor<U>() 

    init(block: (Processor<U>)->Void) { 
     block(Processor(processor: myProcessor)) 
    } 
} 

それとも、あなたはプライベートにしたいプロセッサの複数の内部実装を持っている場合、あなたはプライベートプロトコルを使用することができ、しかし、鍵は、外界がPATではなく、タイプイレーサーしか見ないということです。

private protocol Processing { 
    associatedtype Element 
    func process(element: Element) 
} 

private struct MyProcessor<T>: Processing { 
    func process(element: T) {} 
} 

struct Processor<T> { 
    private let _process: (T) ->() 
    fileprivate init<P: Processing>(_ processor: P) where P.Element == T { 
     _process = processor.process 
    } 
    func process(element: T) { _process(element) } 
} 

class Machine<U> { 
    private let myProcessor = MyProcessor<U>() 

    init(block: (Processor<U>)->Void) { 
     block(Processor(myProcessor)) 
    } 
} 
+0

ありがとうございました。私のコードがやっていたことをちょっとあいまいにしていますが、私は要点を得ています。私はとにかくしようとしていたのと同じ目標を達成しています。 – SeanCAtkinson

関連する問題