2015-11-11 14 views
7

私は2日間、私たちのアプリの簡単なDependency Injectionシステムを迅速に作成しようとしています。私はどのような解決策にも柔軟に対応していますが、何かが欲しいので、 "このプロトコルに準拠したものを私に渡してください"と言うことができます。返される実際のタイプは、私は、ジェネリック医薬品を含む非常に多くの事を試みたが、それは本当に今、私は裸の基礎までだ働くことができないことを把握するために管理している、このような何か(?):クラスがプロトコルに準拠しているかどうかをチェック

protocol AProtocol { 

} 

class AClass: AProtocol { 

} 

class MyDiThing { 
    public static func objectConformingTo(aProtocol: Any) -> Any? { 
     // And here I want to do something like 
     if AClass is aProtocol { 
      return AClass() 
     } 
     return nil 
    } 
} 

// The calling code .. 
let aObject = MyDIThing.objectConformingTo(AProtocol) 

それだ美しいではない、I知っているけど、今はデカップリングの問題を解決している限り、パフォーマンス/悪いコードについてはそれほど気にならない(MyDIThingクラスに含まれることが好ましい)。これが迅速に不可能な場合、私は他のソリューションにもオープンしています。 NSStringFromProtocolというキーを持つ辞書とそのクラスである辞書、インバウンドプロトコルの辞書にサブスクライブしてクラスをインスタンス化するだけで、私は同様のソリューションをobjective-cで成功させました。スーパーシンプル。迅速に不可能と感じる!

答えて

4

obj-cをインポートすると、以前のようなことができます。

そうでなければ、プロトコルは同じ方法で存在しないので難しいです。あなたの工場の登録ベースのシステムを考えてみましょう。それぞれのクラスは、そのクラスの新しいインスタンスを返すために呼び出すことができる関数またはクロージャを提供することによって自分自身を登録し、登録は文字列または他の型の識別子に照合します。これはプロトコルタイプを持つのが良いでしょうが、obj-cでは文字列変換を使って同じことをやっていました。非常に汎用的なものにするために、Equatableのものに登録することができます。

+8

'if let foo = bar as? MyProtocol {/ * barはプロトコルに準拠しています... fooはMyProtocol型であり、メソッドはそれで呼び出すことができます* /} ' – nhgrif

+0

enumをキーとクロージャーを値として使用して登録ベースの迅速なアプローチを行いました。良い仕事。 –

7

nhgrifによって与えられたコメントは、オプションのバインディングを使用する必要がありスウィフト2. の正しい答えです:

if let aObjectWithAProtocol = aObject as? AProtocol { 
    // object conforms to protocol 
    someObject.someFunction(aObjectWithAProtocol) 
} else { 
    // object does not conform to protocol 
} 

オブジェクトができる場合、このif let something = obj as? type文はとチェックを結合オプションと呼ばれています

このような場合は、オプションの(as?)またはの強制解除コード(0)を使用できます。)オブジェクトです。

0

この機能は完全にあなたの要件を満たしています:

bool _swift_typeIsTargetType(id sourceType, id targetType)

それは迅速なタイプがターゲットタイプであるかどうかを確認することができます(同じタイプまたはサブクラスである、または対象のプロトコルに準拠)、isのように動作します迅速なオペレータ。しかし、それはない例えば、タイプのためです:

bool _conformsToProtocols(const OpaqueValue *value, const Metadata *type, const ExistentialTypeMetadata *existentialType, const WitnessTable **conformances) 

オプションの結合が同じではありません:それはlibswiftCore.dylibでプライベートAPIを使用しています

let sourceType: Any.Type = type(of: self) 
let targetType: Any.Type = AnyProtocol.self 
let result = _swift_typeIsTargetType(sourceType, targetType) 

、迅速なソースコードCasting.cppを参照してください。また、適合性を確認することができますが、動的にチェックするタイプを与えることはできません。

let targetType: Any.Type = AnyProtocol.self 
//error: use of undeclared type: 'targetType' 
if let _ = aObject as? targetType { 
    // object conforms to protocol 
} else { 
    // object does not conform to protocol 
} 

この機能はZIKRouterに使用されています。これはモジュールルーターであり、Dependency Injectionフレームワークです。プロトコルを使用してモジュールを検出し、依存関係を注入します。あなたは、「何らかのプロトコルに準拠したモジュールを見つける」のようなことをしたいなら、それを試すことができます。

関連する問題