Use Self-requirement in Protocols in Swift
Written by Team Kodeco
A protocol in Swift is a set of rules that a class, struct or enum must follow. Sometimes you need to make sure that the class or struct that conforms to a protocol must implement a certain method or property itself, instead of using an extension. This is where the Self
keyword comes in.
Let’s take a look at an example. You have a protocol called SelfPrintable
which requires a method called printSelf()
. This method should return a string.
protocol SelfPrintable {
func printSelf() -> String
}
Now you have a class called MyClass
which conforms to the SelfPrintable
protocol.
class MyClass: SelfPrintable {
var name: String
init(name: String) {
self.name = name
}
func printSelf() -> String {
return "My name is \(name)"
}
}
Now let’s say you want to add a method to the SelfPrintable
protocol that checks if two instances of the class that conforms to the protocol are equal. You can do this using an extension and the Self
keyword.
extension SelfPrintable where Self: Equatable {
func isEqual(to other: Self) -> Bool {
return self == other
}
}
The Self
keyword in the where
clause of the extension is used to specify that the extension should only be applied to types that conform to the SelfPrintable
protocol and also conform to the Equatable
protocol.
The isEqual(to:)
function is defined in this extension and it uses the Self
keyword in the parameter type to specify that the method should work with the same type that conforms to the SelfPrintable
protocol. Inside the function, the self == other
comparison is used to check if two instances of the conforming type are equal.
Finally, you’ll make MyClass
conform to the Equatable
protocol and implement the ==
function.
class MyClass: SelfPrintable, Equatable {
var name: String
init(name: String) {
self.name = name
}
func printSelf() -> String {
return "My name is \(name)"
}
static func == (lhs: MyClass, rhs: MyClass) -> Bool {
return lhs.name == rhs.name
}
}
Now you can create two instances of MyClass
and check if they are equal.
let myClassA = MyClass(name: "A")
let myClassB = MyClass(name: "B")
print(myClassA.isEqual(to: myClassB)) // prints "false"
In summary, using the Self
keyword in a protocol’s requirement allows you to specify that a method or property must be implemented by the conforming type itself, not just by an extension. This can help to ensure that the class or struct that conforms to the protocol follows the rules of the protocol correctly.