0

I'm new to Swift. Making a pet project that works with Bluetooth Low Energy (BLE) devices. Thanks to Google found out how to run it (scan, connect etc). But still don't understand how it exactly works. The code is next:

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
    }
}

The question is why do these methods have the same name? I see that they have different parameters (with pretty clear naming), but how Swift knows which method to call?

P.s. Maybe it doesn't fit my perception model because of JS background. Anyway, much appreciate any help

NeMaksym
  • 33
  • 5

2 Answers2

2

Others are calling this "overloading," but it isn't. Overloading is when functions are distinguished only by their types (and Swift supports this). That's not what is happening here. The difference between these functions is their names, just like in "normal" functions. Swift is similar to Objective-C (and Smalltalk, but unlike most languages) in how it names functions. The names of these functions are (following the ObjC tradition):

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

As you can see, these are three completely different names, and so are three different functions without anything complex like overloads getting involved.

In most languages, the names of the parameters are not part of the functions name. But in Smalltalk, ObjC, and Swift, they are. This is not like "named parameters" in Python. The name of the function includes these parameter names, in order, and easily distinguish one from another. If Swift hadn't carried this over from ObjC, it would have been extremely difficult to bridge the two languages as well as they are.

Note that this kind of function naming, where the "base" part of the function name is the name of the caller ("centralManager"), is from the ObjC/Cocoa tradition. While it's common in Swift because of Cocoa (i.e. iOS), it is not actually common in "pure Swift," which generally doesn't use the delegate pattern like this (you never see this in SwiftUI, for example). So what you're really seeing here is ObjC automatically transliterated into Swift.

But distinguishing Swift functions by their full (including parameters) name is extremely common and "Swifty." You see it most commonly in init methods, but it happens all over.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Is the specific naming scheme actually relevant for anything besides ABI compatibility concerns? Does it allow anything special (runtime lookup by string or the like)? Name-mangling in general is seen in other languages too (C++ does it, though I'm not sure any part of the mangling scheme is standardized at the language level); the additional information might be interesting, but it's not necessary to understand why any statically & strongly typed language *could* use overloading (not all do), while dynamically or weakly typed languages (mostly scripting languages) can't. – ShadowRanger Oct 08 '21 at 20:11
  • 1
    @ShadowRanger This isn't related to name mangling at all. Swift has its own name mangling scheme that's separate from this. This has nothing to do with ABI compatibility (it existed from Swift 1, long before ABI resilience). It's a fundamental to the names of Swift functions. It's part of how you take references to functions. It's the name. ObjC and Smalltalk are dynamic languages, and do it exactly this way (and that's why Swift does it this way). – Rob Napier Oct 08 '21 at 20:13
  • BTW, the "mangled" name of the `centralManager(_:didConnect:)` is: `$s1x10BLEManagerC14centralManager_10didConnectySo09CBCentralC0C_So12CBPeripheralCtF` (assuming this is in a module called "x"). That string is generally useless inside of Swift. – Rob Napier Oct 08 '21 at 20:20
  • 1
    @RobNapier Thank you for an important clarification. Am I understand it correctly, in the first place Swift distinguish functions by name (just treat names in a way you described) and then, if we have two functions with identical name, the "overloading" takes place? – NeMaksym Oct 08 '21 at 20:31
  • Yes, Swift supports overloading for functions or methods that have identical names, but different parameter or return types. ObjC does not support that, so those cannot be bridged to ObjC. – Rob Napier Oct 08 '21 at 20:33
  • 1
    Also note the difference between the "external" parameter name which is part of the function's name (`_` in the case of the first parameter) and the "internal" parameter name (`central`) which is not part of the function's name. Two functions that differ only by their internal parameter names would collide. – Rob Napier Oct 08 '21 at 20:34
  • The answer is more than I expected. Much appreciated! It's uncomfortable to ask, but if you'll have a free minute, may you please look at my other [question](https://stackoverflow.com/questions/69498891/how-to-store-value-received-in-delegate-class-inside-external-one)? It's more about app design, I guess. So in case you have something in mind, it would be brilliant – NeMaksym Oct 08 '21 at 20:49
-2

Swift is a bit different from javascript as it's both compiled and typed.

This pattern is called method overloading (function overloading) and is a common pattern in many programming languages.

While in js you can call a function without sending the appropriate arguments to the function, this is not possible in swift. So swift knows which method to use based on which arguments you call it with.

Moriya
  • 7,750
  • 3
  • 35
  • 53