首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Swift 3型铸造

Swift 3型铸造
EN

Stack Overflow用户
提问于 2016-12-26 23:55:54
回答 3查看 3.3K关注 0票数 0

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

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

有人知道这是否可行吗?

更新

我把你和我的第一个代码片段搞混了。希望第二点更有意义。由于@portella的回答,我做了一些改变,但仍然不够。

代码语言:javascript
复制
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
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-12-29 09:43:26

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

代码语言:javascript
复制
protocol Something {
    static func doSomething()
}

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

还有一个通用函数。如果它获得了Something类型,它就调用它的静态方法(不涉及对象)。

有两种方法可以做到这一点:超载和铸造。

重载(@portella的信用卡)

代码语言:javascript
复制
func someFunction<T: Something>() {
    T.doSomething()
}

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

强制铸造(使用@Hiron中提到的类型检查)

代码语言:javascript
复制
func someFunction<T>() {
    if T.self is Something.Type {
        (T.self as! Something.Type).doSomething()
    } else {
        // does something else
    }
}
票数 0
EN

Stack Overflow用户

发布于 2016-12-27 00:11:38

这是否符合你的需要:

代码语言:javascript
复制
protocol Loggable {
    func log()
    static func staticLog()
}

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

您确保发送到函数中的所有对象都符合协议Loggable

对我来说,我不喜欢这样,但希望下面的解决方案能有所帮助(我强烈推荐第一个解决方案):

代码语言:javascript
复制
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())将返回:

编辑:关于更新,您要检查参数类型还是参数类型?您没有将任何参数发送到您的函数中,这似乎很奇怪。我想你会想要验证它,而不是返回,我想。这就是你想要达到的目标吗?

代码语言:javascript
复制
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,则可以在函数声明中使用约束进行操作。

示例:

代码语言:javascript
复制
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进行动态转换和打字

希望这有帮助

票数 1
EN

Stack Overflow用户

发布于 2016-12-27 02:58:15

也许你应该写

代码语言:javascript
复制
if T.self is Coding.Type

而不是

代码语言:javascript
复制
if T.self is Coding
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41337409

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档