Swift 为什么这个带有可选参数的方法不重写基类方法?
结果是“a”,但我希望它是“b”。我想知道为什么,以及如何在没有参数的情况下调用Swift 为什么这个带有可选参数的方法不重写基类方法?,swift,Swift,结果是“a”,但我希望它是“b”。我想知道为什么,以及如何在没有参数的情况下调用doTest来打印“b” 获得a输出的原因是,您没有调用新方法func-doTest(\uu不同:Bool=true),该方法需要Bool bObjc.doTest(true) // b 实际上,您正在调用从父类AA继承的方法doTest() 如果要覆盖AA中的方法,只需执行以下操作: class BB: AA { override func doTest() { print("b")
doTest
来打印“b”
获得
a
输出的原因是,您没有调用新方法func-doTest(\uu不同:Bool=true)
,该方法需要Bool
bObjc.doTest(true) // b
实际上,您正在调用从父类AA
继承的方法doTest()
如果要覆盖
AA
中的方法,只需执行以下操作:
class BB: AA {
override func doTest() {
print("b")
}
}
let bObjc = BB()
bObjc.doTest()
Class
BB
不会重写AA
中的方法,这意味着BB
上存在两个方法:
func doTest() // inherited
func doTest(_ different: Bool = true) // declared
当你打电话的时候
bObjc.doTest()
编译器必须选择其中一个。它更喜欢没有参数的方法,而不是有默认参数的方法。这是一个不幸的情况。没有办法影响编译器如何用这样的简单Swift消除调用的歧义 让我们看看一些选项:
BB.doTest()
以将调用转发到BB.doTest(:)
#选择器(BB.doTest(:)
指定所需方法的签名B
中的doTest
,并重新路由调用:
AA级{
func doTest(){
打印(“a”)
}
}
BB类:AA{
重写func doTest(){
self.doTest(真)
}
func doTest(u不同:Bool=true){
打印(“b”)
}
}
设bObjc=BB()
bObjc.doTest()
如果不可能,请继续阅读
指定doTest(:)
选择器(ObjC)
您可以指定是否要通过选择器调用doTest()
或doTest(_:)
。但是,如果将方法注释为@objc
,并使类型继承自NSObject
,则只能通过其选择器调用方法。因此,在实践中,这可能是矫枉过正
<代码>导入基础
AA类:NSObject{
@objc func doTest(){
打印(“a”)
}
}
BB类:AA{
@objc func doTest(uu不同:Bool=true){
打印(“b”)
}
}
设bObjc=BB()
bObjc.performSelector(onMainThread:#selector(BB.doTest(:)),with:nil,waitUntilDone:true)
使用协议消除歧义
您可以通过拆分类型来帮助编译器选择正确的解决方案,其中进一步定义了doTest()
和doTest(\)
。使用一个协议,然后将“代码”> doTest< /Cord>消息的接收方提交给协议,让编译器知道它应该使用协议中定义的方法。
步骤1:提取协议
议定书本身:
协议点测试特定{
func doTest(uu不同:Bool)
}
不幸的是,您不能在协议的方法定义中指定默认参数值。只有实现可以定义默认参数
步骤2:使用BB
类中的协议
铸造<代码>(BOBJC为doTestApple)将告诉编译器不要考虑<代码> AA. doTest。但是,由于协议未指定默认参数,您现在必须在调用站点上提供值:
AA级{
func doTest(){
打印(“a”)
}
}
BB类:AA,DoTestSpecific{
func doTest(u不同:Bool=true){
打印(“b”)
}
}
设bObjc=BB()
(bObjc作为DoTestSpecific)。doTest(假)
步骤3:将实现移动到协议扩展
cast(bObjc作为DoTestSpecific)
的结果不知道BB
的方法实现及其附带的默认参数值
但是,您可以将实现移动到协议扩展,从而使实现不需要知道参数,甚至不需要知道强制转换的结果
最终代码:
AA级{
func doTest(){
打印(“a”)
}
}
协议点测试特定{
func doTest(uu不同:Bool)
}
扩展点特定{
func doTest(u不同:Bool=true){
打印(“b”)
}
}
BB类:AA,DoTestSpecific{
}
设bObjc=BB()
(bObjc作为DoTestSpecific).doTest()
这正如预期的那样有效。它需要在协议扩展中添加协议和实现。但是现在在呼叫网站上已经没有了模棱两可的地方了
如果示例代码更复杂,并且包含对对象状态或其他对象的依赖关系,那么实现这一点可能会更加困难甚至不可能。您的用例是什么?你什么时候有过这样的实现?你上面的例子是一个编译器问题这个
func doTest(\uu不同:Bool=true)
有一个func doTest()
的变量,编译器甚至不应该编译这个代码,因为基类有一个类似的1func doTest(\uu不同:Bool=true)
已声明,但有一个变量func doTest()
,您应该澄清这一点
bObjc.doTest()