Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

swift protocol extension default implementation vs actual implementation in class

Consider the following code:

protocol MyProtocol {
    static var name: String { get }
}

extension MyProtocol {
    static var name: String {
        return "unnamed"
    }
}

// does not specify its own name
class MyClass: MyProtocol {

}

//specifies its own name!
class MyClass2: MyProtocol {
    static var name: String {
        return "Specific name"
    }
}

let myClass = MyClass()
print("\(MyClass.name)")
//>>"unnamed"

let myClass2 = MyClass2()
print("\(MyClass2.name)")
//>>"Specific name"

Does swift guarantee that for classes (such as in this case MyClass2) that have an actual implementation of a protocol property, in this case "name", that this is used from the class, and not the one of the default "name" implementation via the protocol extension?

like image 947
HixField Avatar asked Apr 24 '26 09:04

HixField


1 Answers

Having a default implementation for a required protocol function/property means that your conforming types won't have to implement that function/property, they can use the default implementation instead.

However, if a conforming type does implement the function/property, then the compiler will always call the more specific implementation, namely the one in your conforming class and not the default one.

So even if you stored an instance of MyClass2 in a variable of type MyProtocol, you'd still get the MyClass2 implementation when accessing the property on the variable.

let myClass2: MyProtocol = MyClass2()
type(of: myClass2).name // "Specific name"

The behaviour is different for non-required properties/functions declared and defined in a protocol extension. If you declare a property/function in the protocol extension only, then even if you provide a different implementation for that in a conforming class, you won't be able to access that implementation from a variable whose type is the protocol type rather than the specific conforming type.

protocol MyProtocol {
    static var name: String { get }
}

extension MyProtocol {
    static var name: String {
        return "unnamed"
    }

    // Optional protocol requirement
    static var nonRequired: String {
        return "nonRequired"
    }
}

// does not specify its own name
class MyClass: MyProtocol { }

//specifies its own name!
class MyClass2: MyProtocol {
    static var name: String {
        return "Specific name"
    }

    // Specific implementation
    static var nonRequired: String {
        return "Specific"
    }
}

let myClass = MyClass()
MyClass.name

let myClass2: MyProtocol = MyClass2()
type(of: myClass2).name // "Specific name"
type(of: myClass2).nonRequired // "nonRequired"
MyClass2.nonRequired // "Specific"
like image 175
Dávid Pásztor Avatar answered Apr 26 '26 01:04

Dávid Pásztor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!