簡體   English   中英

調用具有符合協議的類型變量的泛型函數

[英]Invoking a generic function with a type variable conforming to a protocol

在一個泛型函數中,我想測試符合某個協議的給定對象是否為給定類型。 如果將具體的類類型作為參數傳遞給檢查功能,則效果很好。 但是,當我為類型使用變量(使用三元運算符)時,出現錯誤:

無法使用類型為“ (AnyObject, of: P.Type) ”的參數列表調用“ isObject

另外,將類型變量P.ProtocolP.Protocol也無濟於事,因為:

在參數類型“ P.Protocol ”中,“ P ”不符合預期的類型“ 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)

問題是,與通用占位符T ,當T是協議類型PT.TypeP.Protocol P.Type 換句話說,它采用描述協議本身的元類型,而不是描述符合協議類型的元類型。 這種區別很重要,因為協議不符合自己

您的情況下的一種解決方案是在P.Type元類型周圍引入包裝器,該包裝器在P.Type程序中使用通用占位符,以便為您存儲閉包以執行is check。

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)
    }
}

這是我在對此問答的回答中展示的包裝程序的專用版本,在該版本中,我還展示了如何在Apple平台上解除T.self == base的限制(但此限制不應成為您的問題)案件)。

您現在可以像這樣使用包裝器:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM