web-dev-qa-db-ja.com

このプロトコルが「一般的な制約としてのみ使用できる」のはなぜですか?

私はSwiftで次のことを試みています:

protocol ProtocolWithAlias {
    typealias T
}

protocol AnotherProtocol {
    func someFunc() -> ProtocolWithAlias
}

しかし、エラーが発生します:Protocol 'ProtocolWithAlias' can only be used as a generic constraint because it has Self or associated type requirements

このようなことをすることは可能ですか?エラーメッセージ(または少なくとも "only be used as a generic constraint "の部分)は私にはあまり意味がないようです。

最新のXcode 6ベータ3を使用しています。

ありがとう!

27
MatthewSot

これを試して:

func someFunc<T:ProtocolWithAlias>() -> T
23
Catfish_Man

これを実装することは、コントロールを反転することで可能です。someFuncから値を返す代わりに、ProtocolWithAliasを実装する任意のタイプを受け入れることができるコンシューマを渡し、それで何かを行います。

protocol ProtocolWithAlias {
    typealias T
}

protocol ProtocolConsumer {
    func consume<T: ProtocolWithAlias>(value: T)
}

protocol AnotherProtocol {
    func someFunc(consumer: ProtocolConsumer)
}

このトリックは、関数を 継続渡しスタイル(CPS) に変換することとして知られています。残念ながら、私はこれをCPSなしで実装する方法を見つけることができませんでした。私たちが探している型システムの機能は存在型です(そして this スレッドは素晴らしい説明があります)が、Swiftはそれらをまだサポートしていません)と思います。


他の答えが正しくないのはなぜですか?このシグネチャの意味:

func someFunc<T:ProtocolWithAlias>() -> T

この関数は、実装するすべてのタイプに対してタイプTの値を返すことができるということですProtocolWithAlias thatcallerが選択しますが、calleeによって選択されることを望みました。

この関数の賢明な実装を書くことさえ不可能です。 someFuncの実装があるとしましょう:ProtocolWithAliasを実装する新しいクラスを作成し、someFuncにこのクラスのインスタンスを作成するように要求することができます。

class Uninhabited: ProtocolWithAlias {
    typealias T = Int
    init(nope: Uninhabited) {}
}

...

let impossible: Uninhabited = someFunc<Uninhabited>()
13
Paweł Nowak