更改泛型类

时间:2016-02-11 13:03:56

标签: swift generics

请考虑以下课程:

// 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)'。编译器似乎无法理解BT是一回事吗?

另请注意,我无法定义var entities = [B](),因为我需要将此数组传递给AbstractService方法中的另一个函数。

2 个答案:

答案 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)'。编译器似乎无法理解BT是一回事吗?

只是为了澄清事情。在编辑代码示例中,<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)'
    }
}

现在让我们说,我们将来会添加一个新类型DB的子类型并实例化一个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

虽然我的回答并没有真正解决您的问题,但我认为它应该让您更接近解决方案。

相关问题