在Swift中切换泛型类中的泛型类型

时间:2017-03-07 10:12:45

标签: ios swift generics swift3 switch-statement

我最近尝试在iOS 10中编写Measurement类型的扩展程序,切换案例超过通用 UnitType的类型。我想要做的是根据单位类型在UILabel上指定不同的字符串输出。我的目标是简化用法

我想出的解决方案为每种类型的泛型定义一个方法,如下所示:

func localizedDescription(for length: Measurement<UnitLength>) -> String {
    // some code
}

func localizedDescription(for speed: Measurement<UnitSpeed>) -> String {
    // some code
}

// etc.

我真正想要的是不同的东西但是我无法让它发挥作用。也许你可以,或者它现在是Swift的限制。我准备了一个Swift Playground来详细解释这个。

示例游乐场代码

以下是应该复制情况的代码:

import Foundation

//: Example Classes

class GenericType: NSObject {
    // some code

    var value: Double {
        preconditionFailure("Must be overridden in subclasses.")
    }
}
class GenericSubType1: GenericType {
    override var value: Double { return 5 }
}
class GenericSubType2: GenericType {
    override var value: Double { return 10 }
}

// Note that the class is predefined in a different place, so I can't use the body directly.
class SomeClass<T: GenericType> {
    var valueType: T
    init(valueType: T) {
        self.valueType = valueType
    }
}

Switch-Case Extension

这是我使用开关案例的第一个方法

//: Switch-Case in Extension

extension SomeClass {
    var localizedDescription: String {
        switch T.self { // `type(of: T)` doesn't work, `T` does neither
        case is GenericSubType1:
            return "\(valueType.value) times"

        case is GenericSubType2:
            return "\(valueType.value) people"

        default:
            preconditionFailure("Forgot to define a description for generic subclass: \(T.self).")
        }
    }
}

我收到了一条警告但在两条case行中指出:

  

从'T.Type'转换为无关类型'GenericSubType1'始终失败

我不确定为什么这会给我这个警告,我希望这能按预期工作。有人可以解释一下吗?而且,你最好如何解决这类问题?

2 个答案:

答案 0 :(得分:1)

在撰写问题时,我尝试了其他一些方法,并提出以下解决方案:

//: Multiple Extensions

extension SomeClass where T: GenericSubType1 {
    var localizedDescription: String {
        return "\(valueType.value) times"
    }
}

extension SomeClass where T: GenericSubType2 {
    var localizedDescription: String {
        return "\(valueType.value) people"
    }
}

现在,当我运行以下代码时,输​​出符合预期:

SomeClass(valueType: GenericSubType1()).localizedDescription // => "5.0 times"
SomeClass(valueType: GenericSubType2()).localizedDescription // => "10.0 people"

这个不涉及开关案例,所以如果你能做到这一点,我会很高兴听到你的回答。但这可以作为扩展,所以我想分享。

答案 1 :(得分:0)

如果你想在这种情况下使用开关,你有两个选择:

extension SomeClass {
    var localizedDescription: String {
        switch valueType {
        case is GenericSubType1:
            return "\(valueType.value) times"

        case is GenericSubType2:
            return "\(valueType.value) people"

        default:
            preconditionFailure("Forgot to define a description for generic subclass: \(T.self).")
        }
    }
}

extension SomeClass {
    var localizedDescription: String {
        switch T.self {
        case is GenericSubType1.Type:
            return "\(valueType.value) times"

        case is GenericSubType2.Type:
            return "\(valueType.value) people"

        default:
            preconditionFailure("Forgot to define a description for generic subclass: \(T.self).")
        }
    }
}