I’m not sure why many developers (even some senior developers) confuse Protocols with Object and Struct.
You can think of Protocols as a superclass with some rules. When you conform to that class you’ll have to simply obey those rules. In this case these rules can be methods and properties. Let’s look at an example so you’ll get a clear idea.
Let’s define our Protocol first.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protocol Animal{ | |
func run() | |
func stop() | |
} |
Now you see the main difference between a Class and Protocol. You don’t implement your methods here in Protocol. It’s simply just defined.
Let’s create a Cat class now.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Cat{ | |
} |
Now conform the Cat class to the Animal protocol as below
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Cat : Animal{ | |
} |
Oops but the compiler throws an error yeah?
Playground execution failed: error: Protocols.playground:4:7: error: type ‘Cat’ does not conform to protocol ‘Animal’
class Cat : Animal{
^
Protocols.playground:1:10: note: protocol requires function ‘stop()’ with type ‘() -> ()’; do you want to add a stub?
func stop()
Error message is clear right? It wants you to conform to the protocol. That means you need to implement the methods in the Protocol. Let’s see how to do it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Cat : Animal{ | |
func run() { | |
print("Cat is running now") | |
} | |
func stop() { | |
print("Cat has stopped now") | |
} | |
} |
Cool! now there is no error. Let’s create Dog class and conform to the Animal Protocol just like we did for Cat.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Dog : Animal{ | |
func run() { | |
print("Dog is running now") | |
} | |
func stop() { | |
print("Dog has stopped now") | |
} | |
} |
This way you can make sure that all the classes that are conforming to the protocol will have the same set of methods implemented no matter what. You may ask, “isn’t it polymorphism?”. The answer is YES!
Multiple Protocols
Now you know how to create and conform to a protocol. But can you conform to multiple Protocols? Yes you can Checkout the example below.
Now in the above example the Cat class conforms to both Animal and Eye protocol. As you may have expected it has to conform to both the protocols no matter what.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protocol Animal{ | |
func run() | |
func stop() | |
} | |
protocol Eye{ | |
func closeEyesAndSleep() | |
func openEyesAndLookAround() | |
} | |
class Cat : Animal, Eye{ | |
func run() { | |
print("Cat is running now") | |
} | |
func stop() { | |
print("Cat has stopped now") | |
} | |
func closeEyesAndSleep() { | |
print("Cat is sleeping now") | |
} | |
func openEyesAndLookAround() { | |
print("Cat is looking around") | |
} | |
} |
Properties in Protocol
Now we know that we can add methods in protocol, so what about properties? Yes we can add them too. Look at the example below.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protocol Animal{ | |
var isIdle : Bool? {get set} | |
func run() | |
func stop() | |
} |
Here we have declared a property isIdle. You need to make sure that the property you declare in the protocol is having a getter and setter. Else you might end up with compiler errors.
Now let’s see how it’ll affect the Cat class when we are conforming.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Cat : Animal, Eye{ | |
var isIdle: Bool? = true | |
func run() { | |
print("Cat is running now") | |
} | |
func stop() { | |
print("Cat has stopped now") | |
} | |
func closeEyesAndSleep() { | |
print("Cat is sleeping now") | |
} | |
func openEyesAndLookAround() { | |
print("Cat is looking around") | |
} | |
} |
Cool yeah? Let’s add some logic to our Cat class.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Cat : Animal, Eye{ | |
var isIdle: Bool? = true | |
func run() { | |
isIdle = true | |
print("Cat is running now") | |
} | |
func stop() { | |
isIdle = false | |
print("Cat has stopped now") | |
} | |
func closeEyesAndSleep() { | |
if isIdle == true{ | |
print("Cat is sleeping now") | |
}else{ | |
print("Cat will NOT sleep now") | |
} | |
} | |
func openEyesAndLookAround() { | |
print("Cat is looking around") | |
} | |
} |
Now our Cat class looking complete.
Group with extension
Swift provides us with a option to group all the methods from a Protocol into a block. It’ll increase the readability of the code base. Look at the example below.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Cat : Eye{ | |
var isIdle: Bool? = true | |
func closeEyesAndSleep() { | |
if isIdle == true{ | |
print("Cat is sleeping now") | |
}else{ | |
print("Cat will NOT sleep now") | |
} | |
} | |
func openEyesAndLookAround() { | |
print("Cat is looking around") | |
} | |
} | |
extension Cat : Animal{ | |
func run() { | |
isIdle = true | |
print("Cat is running now") | |
} | |
func stop() { | |
isIdle = false | |
print("Cat has stopped now") | |
} | |
} |
Looks neat yeah?
Creating Objects from Protocols?
Obviously the next question would be, can you create objects from protocol? Answer would be no. Same as you can’t create objects from an interface in Java.
But you can group the objects that has conformed to a protocol in an Array as below.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protocol Animal{ | |
var isIdle : Bool? {get set} | |
func run() | |
func stop() | |
} | |
protocol Eye{ | |
func closeEyesAndSleep() | |
func openEyesAndLookAround() | |
} | |
class Cat : Eye{ | |
var isIdle: Bool? = true | |
func closeEyesAndSleep() { | |
if isIdle == true{ | |
print("Cat is sleeping now") | |
}else{ | |
print("Cat will NOT sleeping now") | |
} | |
} | |
func openEyesAndLookAround() { | |
print("Cat is looking around") | |
} | |
} | |
extension Cat : Animal{ | |
func run() { | |
isIdle = true | |
print("Cat is running now") | |
} | |
func stop() { | |
isIdle = false | |
print("Cat has stopped now") | |
} | |
} | |
class Dog : Animal{ | |
var isIdle: Bool? = true | |
func run() { | |
print("Dog is running now") | |
} | |
func stop() { | |
print("Dog has stopped now") | |
} | |
} | |
let whiteCat = Cat() | |
let blackCat = Cat() | |
let pinkCat = Cat() | |
let blackDog = Dog() | |
let yellowDog = Dog() | |
var animalsArray : [Animal] = [whiteCat, blackCat, pinkCat, blackCat, yellowDog] |
As you can see above animalsArray would only take objects that are conforming to the Animal protocol.
Hope it helped somebody somewhere in need. Good luck!
Subscribe to our mailing list
Subscribe to our mailing list and receive a free udpates
Leave a Reply