2016-12-26 31 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