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

标签 swift generics overriding

上下文:

我有类 A,它是类 B 的父类(super class)。类 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 类无法重写该方法,并出现编译器错误“方法未重写其父类(super class)中的任何方法”

问题:

1)为什么会出现这种情况?

2) 有没有已知的方法可以避免这个问题?我的父类(super class)也是除 B 之外的其他子类的父类(super class),因此在类定义中添加通用参数对于定义单个函数的类型来说是有问题的。

附加说明:

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

按照要求,以防有人觉得需要更大的背景

更扩展的示例版本:

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

        }
    }
}

最佳答案

假设您实际上在某处使用 T 类型,尽管您的代码示例没有显示这一点。

您不需要使用泛型。

在一种用例中,输入类型 T 始终定义为 JSONModel,因此该函数永远无法专门访问除 JSONModel 上定义的属性或方法之外的任何其他属性或方法。无论您引用什么类型,都需要符合 JSONModel(通过继承或作为协议(protocol))。您不妨只使用 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"

关于swift - 无法使用泛型参数覆盖函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38477260/

相关文章:

Kotlin:如何调用扩展方法的 super 实现

symfony - 如何在 Symfony Twig 中显示覆盖复选框的标签

ios - 如何从父ViewController中的ContainerView获取值?

java - 使用带有 DAO 模式的 Guice 进行依赖注入(inject)

ios - 为什么 tableviewcell 返回一个可选的 ("")

C# 特化泛型类

kotlin - 对密封类子项列表进行排序的通用方法

css - 覆盖溢出的基本 CSS : hidden; property

macos - 在 SWIFT OS X 中以编程方式添加和删除 NSTextField

arrays - 在数组中保存和释放闭包