简体   繁体   English

在Swift 3中进行类型转换

[英]Type casting in Swift 3

I want to check whether a generic type conforms to a protocol. 我想检查泛型类型是否符合协议。 If it is, I need to cast the type itself and call a static method against it. 如果是这样,我需要转换类型本身,并针对它调用静态方法。

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

Anybody knows if it's doable? 有人知道这是否可行吗?

UPDATE 更新

I confused you with my first code snippet. 我把我的第一个代码片段弄糊涂了。 Hopefully, second makes more sense. 希望第二更有意义。 I've made some changes thanks to the @portella's answer, but it's still not enough. 感谢@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
}

Does this fit your needs: 这是否符合您的需求:

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

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

You ensure that all the objects sent into the function conforms to the protocol Loggable 您确保发送到函数中的所有对象均符合Loggable协议

For me, i don't like this, but hope the following solution can help (i strongly recommend the first one): 对我来说,我不喜欢这样,但希望以下解决方案能对您有所帮助(我强烈建议您使用第一个):

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

The call log(object: NotLoggableClass()) will return: 💩 Not a loggable object 调用log(object: NotLoggableClass())将返回: 💩 Not a loggable object

The call log(object: LoggableClass()) will return: 👏😕 通话log(object: LoggableClass())将返回: 👏😕

EDIT: regarding the update, do you want to check the argument type or the argument type? 编辑:关于更新,您是否要检查参数类型或参数类型? You are not sending any argument into your function, which seems odd. 您没有在函数中发送任何参数,这似乎很奇怪。 I think you would like to validate it, not the return, i guess. 我想我想您想验证它,而不是回报。 Is this what you are trying to achieve: 这是您要实现的目标:

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

Regarding your solution, i don't understand the objects or where that came from. 关于您的解决方案,我不了解这些objects或它们的来源。 If you want the generic type to conform with the Coding protocol you can make that with a constraint in the function declaration. 如果希望泛型类型符合Coding protocol ,则可以在函数声明中添加约束。

Example: 例:

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

Although, i don't understand the objects, this should be something to be done by the type itself, not by a common helper or something, which seems to me what you are trying. 尽管我不理解这些对象,但这应该由类型本身来完成,而不是由公共帮助者完成,或者在我看来这是您要尝试的事情。

Try to avoid dynamic cast and type with Swift 😉 尝试避免动态转换并使用Swift type键入

Hope that helps 🍻 希望有帮助helps

Maybe you should write 也许你应该写

if T.self is Coding.Type

instead of 代替

if T.self is Coding

Let's say you have a protocol with a static method and a class which implements it: 假设您有一个带有静态方法的协议和一个实现该协议的类:

protocol Something {
    static func doSomething()
}

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

Also there's a generic function. 还有一个通用功能。 If it gets the type Something it calls it's static method (there's no object involved). 如果它得到某类型的Something它将调用它的静态方法(不涉及任何对象)。

There's two ways of doing this: overloading and casting. 有两种方法:重载和强制转换。

Overloading (a credit to @portella) 超载 (归功于@portella)

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

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

Casting (uses a type check mentioned by @Hiron) 强制转换 (使用@Hiron提到的类型检查)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM