请考虑以下课程:
// Models:
class A {}
class B: A { }
// Parsers:
class AbstractParser<T> {}
class ParserB<T: B>: AbstractParser<T> {}
// Services:
class AbstractService<T> {
func parser() -> AbstractParser<T> {
fatalError("This method must be overridden")
}
}
class ServiceA<T: A>: AbstractService<T> {
}
class ServiceB<T: B>: ServiceA<T> {
private let _parser = ParserB()
override func parser() -> ParserB<B> {
return _parser
}
}
我在覆盖Method doesn not override any method from it's superclasses
功能时收到错误parser
。我可以通过改变
class ServiceB<T: B>: ServiceA<T>
到
class ServiceB<T: B>: ServiceA<B>
但这会打破这个问题的解决方案:A variable in generic class gets wrong type
有没有解决方法呢?
修改
谢谢Kenneth Bruno,您的方法有效,但它再次导致了类型的另一个错误。
我添加了课程C
:
class C {
var item = B()
}
和ServiceB
的简单方法:
func doSomething() {
var entities = [T]()
let c = C()
entities.append(c.item)
}
这会导致错误:Cannot invoke 'append' method with an argument list of type '(B)'
。编译器似乎无法理解B
和T
是一回事吗?
另请注意,我无法定义var entities = [B]()
,因为我需要将此数组传递给AbstractService
方法中的另一个函数。
答案 0 :(得分:1)
正如在您的其他问题中,您需要使用泛型类型而不是特定类型,然后方法签名将匹配以覆盖函数。
class ServiceB<T: B>: ServiceA<T> {
private let _parser = ParserB<T>()
override func parser() -> ParserB<T> {
return _parser
}
}
答案 1 :(得分:1)
来自问题编辑:
这会导致错误:
Cannot invoke 'append' method with an argument list of type '(B)'
。编译器似乎无法理解B
和T
是一回事吗?
只是为了澄清事情。在编辑代码示例中,<T: B>
和B
不是一回事。 B
是常规类型,而<T: B>
是通用类型,可能代表B
类型或其任何子类型。
将问题代码与@Kenneth提出的代码合并会产生以下结果,从而导致类型错误
class C {
var item = B()
}
class ServiceB<T: B>: ServiceA<T> {
private let _parser = ParserB<T>()
override func parser() -> ParserB<T> {
return _parser
}
func doSomething() {
var entities = [T]()
let c = C()
entities.append(c.item) // Error: Cannot invoke 'append' method with an argument list of type '(B)'
}
}
现在让我们说,我们将来会添加一个新类型D
,B
的子类型并实例化一个ServiceB<D>
。这会导致函数doSomething()
尝试将B
的实例附加到D
的数组中,这是非法的,这就是编译器引发错误的原因。
使用@Kenneth评论中提出的代码,entities
数组将填入ServiceB<B>
个案例,但ServiceB<D>
中的数组总是空的。
class D: B { }
class ServiceB<T: B>: ServiceA<T> {
...
func doSomething() {
var entities = [T]()
let c = C()
if let item = c.item as? T { entities.append(item) }
}
}
let service = ServiceB<B>()
service.doSomething() // Creates an array of B and append a single B instance on it
let serviceD = ServiceB<D>()
serviceD.doSomething() // Creates an array of D, c.item of type B can't be cast to D, the array will be empty
虽然我的回答并没有真正解决您的问题,但我认为它应该让您更接近解决方案。