是否有一些解决方法可以在不知道定义的元素类型是什么的情况下强制转换为通用基类?

时间:2016-10-09 12:15:05

标签: swift generics swift3

我正在尝试实现一种设计,我可以拥有一个具有通用属性的基类,我可以通过符合协议来更改值。

protocol EnumProtocol {
    static var startValue: Self { get }
    func nextValue() -> Self
}

enum FooState: EnumProtocol {
    case foo1, foo2
    static var startValue: FooState { return .foo1 }
    func nextValue() -> FooState {
        switch self {
        case .foo1:
            return .foo2
        case .foo2:
            return .foo1
        }
    }
}

enum BarState: EnumProtocol {
    case bar
    static var startValue: BarState { return .bar }
    func nextValue() -> BarState {
        return .bar
    }
}


class BaseClass<T: EnumProtocol> {
    var state = T.startValue
}

class FooClass: BaseClass<FooState> {
}

class BarClass: BaseClass<BarState> {
}

是否有可能最终得到类似于此的解决方案,其中元素类型未知且值依赖于nextValue()方法。

let foo = FooClass()
let bar = BarClass()
if let test = bar as? BaseClass {
    test.state = test.state.nextValue()
}

这样可行,但BarState在我的情况下是未知的,很多类将是BaseClass的子类,并且具有不同的状态类型。

let bar = BarClass()
if let test = bar as? BaseClass<BarState> {
    test.state = test.state.nextValue()
}

这是一个简化的例子。在我的例子中,我将获得一个具有state属性的SKNode子类,该属性是具有nextvalue方法的枚举,该方法具有已定义的规则以决定下一个值将是什么。我试图有一个通用的实现,只依赖于nextValue方法返回的内容。是否有更好的模式来实现这一目标?

1 个答案:

答案 0 :(得分:0)

这不适用于此确切方案,因为EnumProtocol不能用作具体类型,因为它具有Self类型要求,但是,为了在其他情况下实现此类行为可以创建基类符合的协议,并在尝试确定对象是否是该类型的某个子类时尝试将对象强制转换为该类型。

考虑以下示例

class Bitcoin { }

class Ethereum { }

class Wallet<T> {
    var usdValue: Double = 0
}

class BitcoinWallet: Wallet<Bitcoin> {

}

class EthereumWallet: Wallet<Ethereum> {

}

let bitcoinWallet = BitcoinWallet() as Any

if let wallet = bitcoinWallet as? Wallet {
    print(wallet.usdValue)
}

由于您所指的错误相同,这不起作用:

error: generic parameter 'T' could not be inferred in cast to 'Wallet<_>'

但是,如果添加以下协议

protocol WalletType {
    var usdValue: Double { get set }
}

并使Wallet符合

class Wallet<T>: WalletType

然后您可以将值转换为该协议并按预期使用它:

if let wallet = bitcoinWallet as? WalletType {
    print(wallet.usdValue)
}