2016-12-26 85 views
-1

我想檢查泛型類型是否符合協議。如果是這樣,我需要將其自身類型轉換爲類型,並調用靜態方法。在Swift中輸入類型3

func log<T>(object: T) { 
    if let C = T as? Loggable { // this line doesn't compile 
     print("\(C.description(of: object))") 
    } else { 
     print("\(object)") 
    } 
} 

有人知道它是否可行嗎?

UPDATE

我讓你感到困惑與我的第一個代碼段。希望第二個更有意義。我已經做了一些改變,感謝@ portella的回答,但這還不夠。

func decodeObject<T>() -> T? { 
    guard let object = objects.first else { 
     return nil 
    } 
    objects.removeFirst() 

    if object is NSNull { 
     return nil 
    } 

    if T.self is Coding.Type { // the condition is fixed, thanks to @Hiron 
     if let data = object as? Data { 
      return type(of: (T.self as! Coding)).from(data: data) as? T 
     } else { 
      return nil 
     } 
    } 

    return object as? T 
} 
+0

爲什麼不只是有'log'的兩個重載?一個用於'可記錄''T',一個用於任何'T'。 – Hamish

+0

@Hamish這可能是一個選項。如果沒有找到答案,我會以這種方式實現它。謝謝 –

+0

我假設不知何故[這個答案](http://stackoverflow.com/questions/41236021/how-do-i-check-if-an-object-is-a-collection-swift/41237381#41237381)應該對你想要做什麼有用。 –

回答

0

比方說,你有一個協議用一個靜態方法和一個實現它的類:

protocol Something { 
    static func doSomething() 
} 

class SomethingConcrete: Something { 
    static func doSomething() { 
     // does something concrete 
    } 
} 

此外還有一個通用功能。如果它獲得類型Something它將其稱爲靜態方法(不涉及任何對象)。

有兩種方法可以做到這一點:重載和鑄造。

重載(貸記@portella)

func someFunction<T: Something>() { 
    T.doSomething() 
} 

func someFunction<T>() { 
    // does something else 
} 

鑄造(使用由@Hiron提到的類型檢查)

func someFunction<T>() { 
    if T.self is Something.Type { 
     (T.self as! Something.Type).doSomething() 
    } else { 
     // does something else 
    } 
} 
1

這是否適合您的需要:

protocol Loggable { 
    func log() 
    static func staticLog() 
} 

func log<L: Loggable>(object: L) { 
    object.log() 
    L.staticLog() 
} 

你確保所有送入函數的對象符合協議Loggable

對於我來說,我不喜歡這樣,但希望以下解決方案可以幫助(我強烈推薦第一個):

protocol Loggable { 
    func log() 
    static func staticLog() 
} 

func log<L>(object: L) { 
    guard let loggableObject = object as? Loggable else { 
     print(" Not a loggable object") 

     return 
    } 

    loggableObject.log() 
    type(of: loggableObject).staticLog() 
} 


final class NotLoggableClass {} 

final class LoggableClass: Loggable { 
    func log() { 
     print("") 
    } 

    static func staticLog() { 
     print("") 
    } 
} 

log(object: NotLoggableClass()) 

log(object: LoggableClass()) 

呼叫log(object: NotLoggableClass())將返回:Not a loggable object

呼叫log(object: LoggableClass())將返回:

編輯:關於更新,你要檢查的參數類型或參數的類型?你沒有向你的函數發送任何參數,這看起來很奇怪。 我想你想驗證它,而不是回報,我猜。 這是你想什麼來實現:

protocol Coding { 
    associatedtype T 

    static func decodeObject<T>(data: Data) -> T? 
} 

extension UIImage: Coding { 
    typealias T = UIImage 

    static func decodeObject<T>(data: Data) -> T? { 
     return UIImage(data: data) as? T 
    } 
} 

關於您的解決方案,我不明白的objects或者是來自何方。 如果您希望通用類型符合Coding 您可以在函數聲明中使用約束條件。

例子:

protocol Coding { 
    associatedtype T 

    static func from(data: Data) -> T? 
} 

func decodeObject<T: Coding>(_ objects: [Data]) -> T? { 
    guard let object = objects.first else { 
     return nil 
    } 

    var objects = objects 
    objects.removeFirst() 

    return T.from(data: object) as? T 
} 

extension String: Coding { 
    static func from(data: Data) -> String? { 
     return String(data: data, encoding: .utf8) 
    } 
} 

雖然,我不明白的對象,這應該是由類型本身來完成,而不是由一個共同的助手什麼的,這在我看來,你是什麼試。

儘量避免動態轉換和類型與斯威夫特

希望幫助

+0

謝謝。我同意你提到的所有觀點。無論如何,你能否檢查最新的問題? –

1

也許你應該寫

if T.self is Coding.Type 

,而不是

if T.self is Coding