Swift泛型类和带有条件泛型的扩展



我有以下类:

class MyClass<T: BaseClass> {
let aThing = T()
func someMethod() {
configure()
}
}

class SubTypeAOfBaseClass: BaseClass { ... }
class SubTypeBOfBaseClass: BaseClass { ... }

configure中,我想根据其类型配置aThing。因此,我创建了一个协议Configurable和一个扩展:

protocol Configurable {
func configure()
}
extension MyClass: Configurable where T == SubTypeAOfBaseClass {
func configure() {
print("Configuring SubTypeAOfBaseClass")
aThing.doSomethingA()
}
}

我得到的错误是在CCD_ 4中,在那里我调用CCD_;引用实例方法configure((需要类型T和SubTypeAOfBaseClass等效。

当我添加以下扩展时的另一个错误:

extension MyClass: Configurable where T == SubTypeBOfBaseClass {
func configure() {
print("Configuring SubTypeBOfBaseClass")
aThing.doSomethingB()
}
}

错误变为"0";在调用实例方法configure"时没有完全匹配;和在线

extension MyClass: Configurable where T == SubTypeBOfBaseClass {

我得到错误";MyClass与可配置协议的一致性存在冲突,即使条件边界不同,也不能有多个一致性">

应该工作,但显然我错过了一些东西,或者我对如何实现我想要的东西的理解是错误的。

考虑当TBaseClass时,或者当T是我定义为的AnotherSubclass时的情况

class AnotherSubclass : BaseClass {
}

会发生什么?当TAnotherSubclass时,您还没有声明对Configure的一致性!

这里真的只有两个(不错的(选择。

  1. T既不是SubTypeAOfBaseClass也不是SubTypeBOfBaseClass时,您希望configure不执行任何操作
  2. 您只希望MyClass<SubTypeAOfBaseClass>MyClass<SubTypeBOfBaseClass>是有效类型——MyClass<BaseClass>MyClass<AnotherSubclass>会导致编译器错误

选择2在Swift中不可用。这将需要类似于Java或Kotlin中的密封类型的东西。

选择1可以这样做:

class BaseClass {
...
func configure() {

}
}
class SubTypeAOfBaseClass: BaseClass {
...
override func configure() {
print("Configuring SubTypeAOfBaseClass")
doSomethingA()
}
}
class SubTypeBOfBaseClass: BaseClass {
...
override func configure() {
print("Configuring SubTypeAOfBaseClass")
doSomethingB()
}
}
class MyClass<T: BaseClass> {
let aThing = T()
func someMethod() {
aThing.configure()
}
}

您可能会注意到,configure的每个实现都已移动到基类中。如果你想在MyClass中实现它们,你必须手动检查类型:

class MyClass<T: BaseClass> {
let aThing = T()
func someMethod() {
if let selfA = self as? MyClass<SubTypeAOfBaseClass> {
selfA.configure()
} else if let selfB = self as? MyClass<SubTypeBOfBaseClass> {
selfB.configure()
}
}
}
extension MyClass where T == SubTypeAOfBaseClass {
func configure() {
print("Configuring SubTypeAOfBaseClass")
aThing.doSomethingA()
}
}
extension MyClass where T == SubTypeBOfBaseClass {
func configure() {
print("Configuring SubTypeBOfBaseClass")
aThing.doSomethingB()
}
}

这是因为代码中的第二个问题——泛型类型MyClass<SubTypeAOfBaseClass>MyClass<SubTypeBOfBaseClass>的不同参数不能以不同的方式符合协议。不幸的是,这是Swift的局限性。请参阅此处了解更多信息。

最新更新