【问题标题】:Type casting in Swift 3Swift 3 中的类型转换
【发布时间】:2016-12-26 23:55:54
【问题描述】:

我想检查泛型类型是否符合协议。如果是,我需要转换类型本身并针对它调用静态方法。

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

有人知道这是否可行吗?

更新

我的第一个代码 sn-p 让您感到困惑。希望第二个更有意义。感谢@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
}

【问题讨论】:

  • 为什么不只重载两个log?一个用于LoggableT,一个用于任何T
  • @Hamish 这可能是一个选项。如果找不到答案,我会以这种方式实施。谢谢
  • 我认为this answer 应该对你想要做的事情有用。

标签: ios swift swift3


【解决方案1】:

也许你应该写

if T.self is Coding.Type

而不是

if T.self is Coding

【讨论】:

    【解决方案2】:

    这是否符合您的需求:

    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,您可以在函数声明中使用约束来实现。

    例子:

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

    虽然,我不理解这些对象,但这应该是由类型本身完成的,而不是由一个常见的助手或其他东西,在我看来你正在尝试什么。

    尽量避免使用 Swift 进行动态转换和类型 ?

    希望对你有帮助 ?

    【讨论】:

    • 谢谢。我同意你提到的所有观点。无论如何,您能检查一下更新后的问题吗?
    【解决方案3】:

    假设你有一个带有静态方法的协议和一个实现它的类:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多