2017-07-08 4 views
1

一般的な関数では、特定のプロトコルに準拠する特定のオブジェクトが所定の型であるかどうかをテストします。具体的なクラス型がチェック関数のパラメータとして渡された場合にはうまくいきます。私は(三項演算子を使用して)タイプの変数を使用する場合しかし、私はエラーを取得する:P.Protocolに加えて型変数キャスティングプロトコルに準拠した型変数を持つ汎用関数を呼び出す

Cannot invoke ' isObject ' with an argument list of type ' (AnyObject, of: P.Type) '

は、いずれかの助けにはならない、以来:

In argument type ' P.Protocol ', ' P ' does not conform to expected type ' P '

protocol P { 
    static var descr: String {get} 
} 

class A: P { 
    static let descr = "class A" 
} 

class B: P { 
    static let descr = "class B" 
} 

class Test { 
    func isObject<T:P>(_ object: AnyObject, of type: T.Type) -> Bool { 
     print("descr: \(type.descr)") 
     return object is T 
    } 
} 

let a = A() 
let type = (false ? A.self : B.self) as P.Type //as! P.Protocol 
let test = Test() 

test.isObject(a, of: type) 

答えて

0

問題は、TがプロトコルタイプPである場合、一般的なプレースホルダTとすることであるT.TypeP.Protocolないあります。言い換えれば、プロトコルに準拠する型を記述するメタタイプではなく、プロトコル自体をと記述するメタタイプが必要です。 protocols don't conform to themselvesのため、この区別は重要です。

場合によっては、チェックを実行するためのクロージャーを保存するために、イニシャライザー内の汎用プレースホルダーを使用するP.Typeメタタイプのラッパーを導入することをお勧めします。

struct AnyPType { 

    let base: P.Type 
    private let _isInstance: (Any) -> Bool 

    /// Creates a new AnyType wrapper from a given metatype. 
    /// The passed metatype's value **must** match its static value, i.e `T.self == base`. 
    init<T : P>(_ base: T.Type) { 
     precondition(T.self == base, "The static value \(T.self) and dynamic value \(base) of the passed metatype do not match") 
     self.base = T.self 
     self._isInstance = { $0 is T } 
    } 

    func isInstance(_ instance: Any) -> Bool { 
     return _isInstance(instance) 
    } 
} 

これは私がまたアップルのプラットフォーム上でT.self == baseの制限を解除する方法を示します(ただし、この制限は、あなたの中で問題になることはありませんここで私は私の答えto this Q&Aに表示ラッパーの特殊なバージョンであります場合)。

あなたは今ではのようなラッパーを使用することができます。

class Test { 
    func isObject(_ object: Any, of type: AnyPType) -> Bool { 
     print("descr: \(type.base.descr)") 
     return type.isInstance(object) 
    } 
} 

let type = AnyPType(A.self) // or AnyPType(B.self) 

print(Test().isObject(A(), of: type)) 

// descr: class A 
// true 
関連する問題