【问题标题】:How a class has several methods with the same name? [duplicate]一个类如何有多个同名的方法? [复制]
【发布时间】:2021-11-28 17:18:51
【问题描述】:

我是 Swift 新手。制作一个适用于蓝牙低功耗 (BLE) 设备的宠物项目。感谢 Google 发现了如何运行它(扫描、连接等)。但仍然不明白它是如何工作的。接下来是代码:

class BLEManager: CBCentralManagerDelegate, OtherProtocols {
    private var myCentral: CBCentralManager!

    override init() {
        super.init()

        myCentral = CBCentralManager(delegate: self, queue: nil)
        myCentral.delegate = self
    }

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        // This one discover devices
    }

    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        // This one handles connection
    }

    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        // Does some stuff as well
    }
}

问题是为什么这些方法有相同的名称?我看到它们有不同的参数(命名非常清楚),但是Swift如何知道调用哪个方法?强>

附:可能因为 JS 背景不符合我的感知模型。无论如何,非常感谢任何帮助

【问题讨论】:

标签: swift class-method swift-class


【解决方案1】:

其他人称之为“重载”,但事实并非如此。重载是指函数仅通过类型来区分(Swift 支持这一点)。这不是这里发生的事情。这些函数之间的区别在于它们的名称,就像在“普通”函数中一样。 Swift 在命名函数的方式上类似于 Objective-C(和 Smalltalk,但与大多数语言不同)。这些函数的名称是(遵循 ObjC 传统):

centralManager(_:didDiscover:advertisementData:rssi:)
centralManager(_:didConnect:)
centralManager(_:didDisconnectPeripheral:error:)

如您所见,这是三个完全不同的名称,三个不同的函数也是如此,没有任何复杂的东西,例如重载。

在大多数语言中,参数名称不是函数名称的一部分。但在 Smalltalk、ObjC 和 Swift 中,它们是。这不像 Python 中的“命名参数”。函数的名称包括这些参数名称,按顺序排列,并且易于区分。如果 Swift 没有从 ObjC 继承这一点,那么将这两种语言连接起来将会非常困难。

请注意,这种函数命名,其中函数名称的“base”部分是调用者的名称(“centralManager”),来自 ObjC/Cocoa 传统。虽然由于 Cocoa(即 iOS)而在 Swift 中很常见,但在“纯 Swift”中实际上并不常见,它通常不使用这样的委托模式(例如,你在 SwiftUI 中从未见过这种模式)。所以你在这里真正看到的是 ObjC 自动音译成 Swift。

但是通过完整(包括参数)名称来区分 Swift 函数是非常常见的并且是“Swifty”。你最常在init 方法中看到它,但它总是会发生。

【讨论】:

  • 除了 ABI 兼容性问题之外,具体的命名方案是否真的与其他任何事情相关?它是否允许任何特殊的东西(通过字符串或类似的运行时查找)?通常在其他语言中也可以看到名称修饰(C++ 会这样做,尽管我不确定修饰方案的任何部分在语言级别上是否标准化);附加信息可能很有趣,但没有必要理解为什么任何静态和强类型语言可以使用重载(不是全部),而动态或弱类型语言(主要是脚本语言)不能.
  • @ShadowRanger 这与名称修改完全无关。 Swift 有自己的名称修饰方案,与此不同。这与 ABI 兼容性无关(它早在 ABI 弹性之前就存在于 Swift 1 中)。它是 Swift 函数名称的基础。这是您如何引用函数的一部分。这是名字。 ObjC 和 Smalltalk 是动态语言,并且正是这样做的(这就是 Swift 这样做的原因)。
  • 顺便说一句,centralManager(_:didConnect:) 的“错位”名称是:$s1x10BLEManagerC14centralManager_10didConnectySo09CBCentralC0C_So12CBPeripheralCtF(假设这是在一个名为“x”的模块中)。该字符串在 Swift 内部通常是无用的。
  • @RobNapier 感谢您的重要澄清。我是否理解正确,首先 Swift 通过名称区分函数(只需按照您描述的方式处理名称),然后,如果我们有两个名称相同的函数,就会发生“重载”?
  • 还要注意作为函数名称一部分的“外部”参数名称(在第一个参数的情况下为_)和“内部”参数名称(central)之间的区别这不是函数名称的一部分。仅内部参数名称不同的两个函数会发生冲突。
【解决方案2】:

Swift 与 javascript 有点不同,因为它既是编译的又是类型的。

这种模式称为方法重载(函数重载),是许多编程语言中的常见模式。

虽然在 js 中你可以在不向函数发送适当参数的情况下调用函数,但这在 swift 中是不可能的。所以 swift 知道根据你调用它的参数来使用哪种方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    • 2013-08-17
    • 2019-04-21
    • 2021-12-19
    • 2014-01-30
    • 2020-08-31
    相关资源
    最近更新 更多