Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

At runtime, how does Swift know which implementation to use?

protocol A {
    func f()
}

struct S1 : A {
    func f() {
        print("S1")
    }
}

struct S2 : A {
    func f() {
        print("S2")
    }
}

let array: [A] = [S1(), S2()]

for s: A in array {
    s.f()
}

// "S1\n" "S2\n"

If this was an inheritance hierarchy, I would expect Swift to use a v-table to look up the correct implementation. However, the concrete types in array could be anything that implements A, along with any number of other protocols, so how would the Swift runtime know the structure of the object if it was also using v-tables?

like image 760
Ian Warburton Avatar asked Jul 12 '16 15:07

Ian Warburton


People also ask

What is runtime in Swift?

The Swift runtime exports standard metadata objects for Builtin types as well as standard value witness tables that can be freely adopted by types with common layout attributes.

CAN protocols have implementation Swift?

As mentioned in Swift's documentation: “You can use protocol extensions to provide a default implementation to any method or computed property requirement of that protocol.” In fact, not only can you provide a default implementation to methods or computed properties defined in the protocol, you can also add new ones.

How many protocols can a Swift class adopt?

Since classes, structures and, enums can conform to more than one protocol, they can take the default implementation of multiple protocols. This is conceptually similar to multiple inheritance in other languages.

Why protocols are needed in Swift?

In summary, protocols in Swift offer communication between unrelated objects where we define the methods and variables observed in classes, enums, and structs. Because Swift embraces the protocol-oriented paradigm, we can model our system before defining classes, structs, or enums, making the process more efficient.


1 Answers

The Swift runtime uses a Protocol Witness Table which holds pointers to each type's implementations of the protocol methods.

Mike Ash explains it best in his article Exploring Swift Memory Layout, Part II:

The last one, at offset 32 is a "protocol witness table" for the underlying type and the protocol, which contains pointers to the type's implementations of the protocol methods. This is how the compiler is able to invoke methods, such as p(), on a value of protocol type without knowing the underlying type at runtime.

I would also watch the WWDC video Understanding Swift Performance as suggested in the comments by Hamish.

like image 55
JAL Avatar answered Oct 21 '22 12:10

JAL