Swift中如何不给父类加泛型即可修改子类继承的协议关联类型
问题根因
Swift 中类一旦确定了协议关联类型的具体类型,子类就无法再修改该关联类型。同时 Swift 不允许重写属性时变更属性类型,因为这会破坏父类已经约定的类型契约,导致父类指针调用时出现类型安全问题。
以下两种方案都不需要给AnyLayer添加泛型参数,即可满足需求:
方案1:保留继承关系,新增类型安全访问层
保持AnyLayer原有实现不变,子类内部做类型校验,对外暴露类型安全的接口:
// 原有AnyLayer实现不变 class AnyLayer: Layer { public var neurons = [AnyNeuron]() public func neuron(_ neuron: AnyNeuron) { /* Some actions */ } public func neurons(_ neurons: [AnyNeuron]) { self.neurons = neurons } } // 子类实现 final class InputLayer: AnyLayer { // 对外暴露类型安全的神经元数组 var inputNeurons: [InputNeuron] { neurons as? [InputNeuron] ?? [] } // 重写父类方法,添加类型校验,避免非预期类型加入 override func neuron(_ neuron: AnyNeuron) { guard neuron is InputNeuron else { assertionFailure("InputLayer 仅支持添加 InputNeuron 类型") return } super.neuron(neuron) } // 新增类型安全的添加方法,编译时即可校验类型 func add(_ neuron: InputNeuron) { super.neuron(neuron) } }
该方案完全兼容现有依赖AnyLayer的代码,不需要修改上层调用逻辑。
方案2:拆分通用逻辑到基类,子类直接遵守协议实现编译时类型安全
如果需要完全的编译时类型校验,可以把AnyLayer的通用逻辑抽离到不遵守Layer协议的基类中,子类继承基类后自行实现Layer协议:
// 抽离所有Layer通用逻辑的基类,不遵守Layer协议 class BaseLayer { // 原有AnyLayer中的通用逻辑都放到这里 func commonProcess() { /* 通用实现 */ } } // 原有AnyLayer保持不变,供需要通用Layer类型的场景使用 class AnyLayer: BaseLayer, Layer { typealias NeuronType = AnyNeuron var neurons: [AnyNeuron] = [] func neuron(_ neuron: AnyNeuron) { /* 原有实现 */ } func neurons(_ neurons: [AnyNeuron]) { /* 原有实现 */ } } // 自定义子类继承BaseLayer,自行实现Layer协议,关联类型可自由定义 final class InputLayer: BaseLayer, Layer { typealias NeuronType = InputNeuron var neurons: [InputNeuron] = [] func neuron(_ neuron: InputNeuron) { /* 实现逻辑 */ } func neurons(_ neurons: [InputNeuron]) { /* 实现逻辑 */ } }
该方案可以实现编译时的全类型校验,没有运行时开销,也不会影响原有AnyLayer的使用。
内容的提问来源于stack exchange,提问作者Daniil Khrapovitskii
相关产品推荐
相关产品推荐

