无法使用泛型参数覆盖函数

时间:2016-07-20 09:20:57

标签: swift generics override

上下文:

我有一个类A,它是类B的超类。类A也有在类声明中声明的泛型类型,它们被它的子类覆盖。

A类有一个方法,它需要一个不属于类声明的泛型参数。

B类通过从类定义中指定泛型类型来覆盖类定义,并希望覆盖泛型函数。

示例:

class A<U: NSDictionary, Z: NSDictionary> : NSObject
{
    func funcToOverride<T : JSONModel>()
    {

    }
}

class B : A<NSDictionary, NSDictionary>
{
    override func funcToOverride<T:JSONModel>()
    {

    }
}

问题:

B类无法使用编译器错误覆盖该方法“方法不会覆盖其超类中的任何方法”

问题:

1)为什么这首先出现?

2)有没有已知的方法来避免这个问题?除了B之外,我的超类也是其他子类的超类,因此在类定义中添加泛型参数只是为单个函数定义类型而存在问题。

附加说明:

这段代码是严格的!我在一个现有的大型SDK中处理的更复杂代码的示例。我需要通过避免添加与当前上下文无关的协议或其他类来专门解决泛型冲突问题。

根据要求,有人认为需要更大的背景

更广泛的示例版本:

class A<ResponseModel : NSDictionary, RedirectModel : NSDictionary>: NSObject {

    let existingCompletionHandler : (responseModel : ResponseModel?, error : NSError?) -> Void = {
        (responseModel : ResponseModel?, error : NSError?) -> Void in
    }

    func presentWebViewAndWaitForRedirect(redirectQueryPath : String)
    {
        let queryPathToDict : [NSObject : AnyObject] = [:]

        treatRedirectWithResponseParams(queryPathToDict) {[weak self] (model, error) in
            self?.callSomeRandomRequestWithRedirectModel(model)
        }
    }

    func callSomeRandomRequestWithRedirectModel(redirectModel : RedirectModel?)
    {
        let requestResult : [NSObject : AnyObject] = [:]

        treatRequestResponse(requestResult, completionHandler: existingCompletionHandler)
    }

    func treatRedirectWithResponseParams(responseParams : [NSObject : AnyObject], completionHandler : (model : RedirectModel?, error : NSError?) -> Void)
    {
        funcToOverride(responseParams, completionHandler: completionHandler)
    }

    func treatRequestResponse(someRequestResult : [NSObject : AnyObject], completionHandler : (model : ResponseModel?, error : NSError?) -> Void)
    {
        funcToOverride(someRequestResult, completionHandler: completionHandler)
    }

    func funcToOverride<T : NSDictionary>(params : [NSObject : AnyObject], completionHandler : (model : T?, error : NSError?) -> Void)
    {

    }
}


class B: A<NSDictionary, NSDictionary> {

        //wants to provide something additional or different to the base implementation but still respect the base class logic flow
        override func funcToOverride<T : NSDictionary>(params: [NSObject : AnyObject], completionHandler: (model: T?, error: NSError?) -> Void) {

        }
    }

class SomeOtherRandomClass : NSDictionary
{

}

class C: A<NSDictionary, NSDictionary> {

    func someOtherClassCRequest()
    {
        let response : [NSObject : AnyObject] = [:]

        funcToOverride(response) { (model : SomeOtherRandomClass?, error : NSError?) in

        }
    }
}

2 个答案:

答案 0 :(得分:1)

假设您实际上在某处使用了类型T,尽管您的代码示例未显示此内容。

您不需要使用泛型。

在一个用例中,输入类型T始终定义为JSONModel,因此该函数永远不能专门访问除JSONModel上定义的属性或方法之外的任何其他属性或方法。无论您引用哪种类型,都需要符合JSONModel(通过继承或作为协议)。您也可以使用JSONModel。

唯一的另一个用例是你需要访问JSONModel实例的特定成员,在这种情况下你可以使用函数重载。

示例:

protocol JSONModel {
    func hello() -> String
}

class ModelA: JSONModel {
    func hello() -> String {
        return "Hello Model A"
    }
}

class ModelB: JSONModel {
    func hello() -> String {
        return "Hello Model B"
    }

    func goodbye() -> String {
        return "Goodbye Model B"
    }
}

class A<U: NSDictionary, Z: NSDictionary>: NSObject
{
    func fromJSON(t: JSONModel)
    {
        print("From A: \(t.hello())")
    }
}

class B : A<NSDictionary, NSDictionary>
{
    override func fromJSON(t: JSONModel)
    {
        print("From B: \(t.hello())")
    }

    func fromJSON(t: ModelB)
    {
        print("From B: \(t.goodbye())")
    }
}

let a = A()
a.fromJSON(ModelA()) // "From A: Hello A"

let b = B()
b.fromJSON(ModelB() as JSONModel) // "From B: Hello B"
b.fromJSON(ModelB()) // "From B: Goodbye B"

答案 1 :(得分:1)

您可以不使用override关键字。继承正常工作。

import Cocoa
import XCPlayground## Heading ##

class JSONModel {
    required init() {
    }
}

class ModelA: JSONModel {
    var name: String?
    required init() {
    }
}

class ModelB: JSONModel {
    var size: Int?
    required init() {
    }
}

class A<U: NSDictionary, Z: NSDictionary>: NSObject
{
    let prefix = "A"

    func funcToOverride<T: JSONModel>(u: [String: AnyObject], c: (T?) -> Void)
    {
        let t = T()
        (t as? ModelA)?.name = "From A: " + ((u["name"] as? String) ?? "-none-")
        (t as? ModelB)?.size = u["size"] as? Int ?? 0
        c(t)
    }
}

class B : A<NSDictionary, NSDictionary>
{
    let suffix = "B"

    func funcToOverride<T: JSONModel>(u: [String: AnyObject], c: (T?) -> Void)
    {
        let t = T()
        (t as? ModelA)?.name = "From B: " + ((u["name"] as? String) ?? "-none-")

        if t is ModelB {
            return super.funcToOverride(u, c: c)
        }

        c(t)
    }
}

let a = A()

a.funcToOverride(["name": "foo"]) { (m: ModelA?) in
    print("From A: \(m) \(m?.name)")
}

a.funcToOverride(["size": 10]) { (m: ModelB?) in
    print("From A: \(m) \(m?.size)")
}


let b = B()

b.funcToOverride(["name": "bar"]) { (m: ModelA?) in
    print("From B: \(m) \(m?.name)")
}

b.funcToOverride(["size": 10]) { (m: ModelB?) in
    print("From B: \(m) \(m?.size)")
}

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true