Swift 5.3中的继承类正在调用上层类init,而不是预期的继承init

Swift 5.3中的继承类正在调用上层类init,而不是预期的继承init,swift,class,inheritance,Swift,Class,Inheritance,我在斯威夫特车上被一件东西绊倒了。 我继承了类UIAlertController,以便在iPadOS和 class myUIAlertController: UIAlertController { convenience init(title: String?, message: String?, preferredStyle: UIAlertController.Style, interfaceIdiom: UIUserInterfaceIdiom? = UIDevice.current.us

我在斯威夫特车上被一件东西绊倒了。 我继承了类
UIAlertController
,以便在iPadOS和

class myUIAlertController: UIAlertController {
convenience init(title: String?, message: String?, preferredStyle: UIAlertController.Style, interfaceIdiom: UIUserInterfaceIdiom? = UIDevice.current.userInterfaceIdiom) {
    self.init(title: title, message: message, preferredStyle: interfaceIdiom == .pad ? .alert : preferredStyle)
}
现在我遇到了一个问题,当我从这个类创建一个实例时,如下所示:

let actionsheet = myUIAlertController(
        title: "Profile.Change-Image.ActionSheet.Title".localized,
        message: nil,
        preferredStyle: .actionSheet
    )
它从
UIAlertController
调用init,而不是
myUIAlertController

我试过这个:

let actionsheet = myUIAlertController(
        title: "Profile.Change-Image.ActionSheet.Title".localized,
        message: nil,
        preferredStyle: .actionSheet,
        interfaceIdiom: UIDevice.current.userInterfaceIdiom
    )
这是可行的,但我想知道为什么我需要额外的参数
interfaceIdiom

这个问题与文档中的限制无关,
UIAlertController类打算按原样使用,不支持子类化。

独立于基类,当编译器有多个重载函数可供选择时,您总是会遇到此类问题

您的示例与以下内容完全相同:

class Base {
    convenience init(value1:Int) {
        print("Base::init(\(value1))")
        self.init()
    }
}

class Derived : Base {
    convenience init(value1:Int, value2:Int = 123) {
        print("Derived::init (\(value1), \(value2))")
        self.init(value1:value1)  // no recursion here!
    }   
}

var b  = Base(value1:42)                // prints: Base::init(42)
var d1 = Derived(value1:42)             // prints: Base::init(42), not Derived::init (42, 123)
var d2 = Derived(value1:42, value2:99)  // prints: Derived::init (42, 99) ...
问题是:为什么
vard=Derived(value1:42)
调用基类init而不是使用默认参数
value2=123
方便地初始化派生类

其原因是编译器如何选择模糊的函数。 考虑两个功能:

func foo() { print ("foo()")}
func foo(_ value:Int = 42) { print ("foo(\(value))")}
如果有人调用
foo()
,会发生什么?这两个函数可能都有效,因此编译器必须决定选择哪一个。编译器将选择最特定的匹配函数

第一个
foo
始终采用零参数。第二个
foo
有时取零,有时取一个参数。因此,第一个函数比第二个函数更具体,因为它总是并且只接受零个参数。因此:

foo() // prints foo(), not foo(42)

从文档中可以看出:
Important-UIAlertController类旨在按原样使用,不支持子类化。
如果您只想强制使用样式,可以使用
UIAlertController
上的扩展并生成工厂方法。干杯,错过了黄色的重要框。