当前位置: 首页 > 面试题库 >

Swift 2协议扩展未正确调用重写的方法

陈康胜
2023-03-14
问题内容

使用默认实现的Swift
2协议扩展遇到了一个问题。基本要点是,我已经提供了协议方法的默认实现,我将在实现该协议的类中重写该方法。该协议扩展方法是从基类中调用的,然后该基类将调用在派生类中已重写的方法。结果是未调用重写的方法。

我试图将问题提炼到最小的游乐场,以说明以下问题。

protocol CommonTrait: class {
    func commonBehavior() -> String
}

extension CommonTrait {
    func commonBehavior() -> String {
        return "from protocol extension"
    }
}

class CommonThing {
    func say() -> String {
        return "override this"
    }
}

class ParentClass: CommonThing, CommonTrait {
    override func say() -> String {
        return commonBehavior()
    }
}

class AnotherParentClass: CommonThing, CommonTrait {
    override func say() -> String {
        return commonBehavior()
    }
}

class ChildClass: ParentClass {
    override func say() -> String {
        return super.say()
        // it works if it calls `commonBehavior` here and not call `super.say()`, but I don't want to do that as there are things in the base class I don't want to have to duplicate here.
    }
    func commonBehavior() -> String {
        return "from child class"
    }
}

let child = ChildClass()
child.say() // want to see "from child class" but it's "from protocol extension”

问题答案:

不幸的是,协议还没有这样的动态行为。

但是,您可以(在类的帮助下)通过commonBehavior()在中实现ParentClass并在中进行覆盖来做到这一点ChildClass。您还需要一个CommonThing或另一个类来遵循,CommonTrait然后才是的超类ParentClass

class CommonThing: CommonTrait {
    func say() -> String {
        return "override this"
    }
}

class ParentClass: CommonThing {
    func commonBehavior() -> String {
        // calling the protocol extension indirectly from the superclass
        return (self as CommonThing).commonBehavior()
    }

    override func say() -> String {
        // if called from ChildClass the overridden function gets called instead
        return commonBehavior()
    }
}

class AnotherParentClass: CommonThing {
    override func say() -> String {
        return commonBehavior()
    }
}

class ChildClass: ParentClass {
    override func say() -> String {
        return super.say()
    }

    // explicitly override the function
    override func commonBehavior() -> String {
        return "from child class"
    }
}
let parent = ParentClass()
parentClass.say()          // "from protocol extension"
let child = ChildClass()
child.say()                // "from child class"

由于这只是您问题的一个简短解决方案,我希望它适合您的项目。



 类似资料:
  • 扩展说明 RPC 协议扩展,封装远程调用细节。 契约: 当用户调用 refer() 所返回的 Invoker 对象的 invoke() 方法时,协议需相应执行同 URL 远端 export() 传入的 Invoker 对象的 invoke() 方法。 其中,refer() 返回的 Invoker 由协议实现,协议通常需要在此 Invoker 中发送远程请求,export() 传入的 Invoker

  • 协议和扩展 你可以扩展一个已经存在的类型来采纳和遵循一个新协议, 就算是你无法访问现有类型的源代码也行. 扩展可以添加新的属性、方法和下标到已经存在的类型, 并且因此允许你添加协议需要的任何需要. protocol TextRepresentable { var textualDescription: String { get } } // 此处并无Dice这个类, 以及其sides属性

  • 问题内容: 我正在尝试使用Swift协议扩展,却发现这种行为令人困惑。您能帮我得到我想要的结果吗? 请参阅代码最后4行的注释。(如果需要,可以将其复制粘贴到Xcode7游乐场)。谢谢!! 问题答案: 简短的答案是协议扩展不执行类多态性。这是有一定道理的,因为协议可以被结构或枚举采用,并且因为我们不希望仅在没有必要的地方采用协议来引入动态调度。 因此,在中,实例变量(可能更准确地写为)并不意味着您认

  • 本文作为HPB知识库的一种扩展阅读, RLP编码是数据序列化的主要方法,本文介绍RLP编码的主要规则和原理分析,RLP编码具有较好的数据处理效率,尤其是将长度和类型统一作为前缀,实际上RLP是基于ASCII编码的一种结构化扩充,既能表示长度还能表示类型,是一种非常紧凑的结构化编码方案 RLP(Recursive Length Prefix,递归长度前缀)是一种编码算法,用于编码任意的嵌套结构的二进

  • 据我所知,协议缓冲区主要用于控制服务器和客户端代码的项目。我的一般问题是——协议缓冲区能否用于将二进制消息序列化/反序列化到使用现有协议的服务器?所以,我的问题: > 如果协议缓冲区不支持本机微调现有协议的序列化/反序列化方式,那么可以通过扩展添加该功能吗?是否可以以某种方式添加序列化/反序列化方法可以识别的关键字?也许这可以通过扩展或修改protobuf csharp port或protobuf

  • 问题内容: 我遇到了以下代码(Swift 3.1)中解释的问题: 因此,我希望在调用后应打印 _“ SubClassmethodA”_文本。但是由于某种原因,调用了from协议扩展的默认实现。但是,呼叫按预期方式工作。 是协议方法调度中的另一个Swift错误,还是我丢失了一些东西并且代码正常工作? 问题答案: 这就是协议当前调度方法的方式。 协议见证表(有关更多信息,请参见WWDC谈话)用于在协议