[Swift] Protocol Oriented Programming
Preamble?
At WWDC 2015, Apple released Swift 2 with lots of new features to support programming with Swift. One of the features is Protocol Extensions that support extend a protocol. That also means that Protocol is now a very powerful thing and can change the way you write your code. That's also the mark of Protocol Oriented Programming.
To better understand Protocol Oriented Programming, we will learn about the Protocol, the basic component of Protocol Oriented Programming.
What is Protocol?
A protocol can be interpreted as a blueprint to define a set of properties and methods. A protocol can be applied by 1 class, 1 struct or 1 enum. Class / struct / enum when "conform" protocol will give the property and method the values and the corresponding implementation for that protocol.
Example of a protocol
1 | protocol SomeProtocol { // protocol definition goes here var mustBeSettable: Int { get set } var doesNotNeedToBeSettable: Int { get } } protocol Bird { var canFly: Bool func fly() } |
Protocol Oriented Programming
Protocol-oriented programming is an OOP model but it prioritizes the use of protocols and structs instead of using classes.
To better understand Protocol oriented programming, we will make a small example.
First, instead of starting with a class like OOP, we will start with a protocol.
1 | protocol Developer { var programmingLanguage : [String] { get } var handsome : Bool { get } var name : String { set get } } protocol Handsome { var handsomeLevel : Int { get set } } |
Create a struct to conform to the above protocols
1 | enum ProgrammingLanguage: String { case Swift = "Swift" case ObjectiveC = "Objective C" case Java = "Java" } struct AndroidDev: Developer { var programmingLanguage: [String] { return [ProgrammingLanguage.Java.rawValue] } var handsome: Bool { return false } var name: String } struct iOSDev: Developer, Handsome { var programmingLanguage: [String] { return [ProgrammingLanguage.Swift.rawValue, ProgrammingLanguage.ObjectiveC.rawValue] } var handsomeLevel: Int var name: String } |
With the AndroidDev struct, we have nothing to say, AdroidDev conform protocol Developer, so it must implement all variables of protocol Developer.
However, with the iOSDev struct, we will think, if we inherited the Handsome protocol, of course the handsome value must be true, so how do we consider the default for the inheritance structure of the Handsome ???
With protocol extensions, we can easily consider the default values for the protocol easily.
1 | extension Developer where Self: Handsome { var handsome: Bool { return true } } |
With this extension, each struct conform protocol Developer has just conformed to the protocol of Handsome, which will have the default value of handsome = true variable, we can remove the handsome conform biees in the struct.
1 | struct iOSDev: Developer, Handsome { var programmingLanguage: [String] { return [ProgrammingLanguage.Swift.rawValue, ProgrammingLanguage.ObjectiveC.rawValue] } var handsomeLevel: Int { return 10000 } } |
Extending Protocol
Perhaps the most useful feature of the protocol extension is to enable extending external protocols that include protocols defined in Swift standard library or in a third party framework.
We will use it with the above example.
1 | extension CollectionType where Generator.Element: Developer, Generator.Element :Handsome { func theMostHandsomer() -> String { var mostHandsomer = self.first! for handsomer in self { if handsomer.handsomeLevel > mostHandsomer.handsomeLevel { mostHandsomer = handsomer } } return mostHandsomer.name } } let quocnb = iOSDev(handsomeLevel: 10000, name: "Quoc Nguyen") let hoangls = iOSDev(handsomeLevel: 1, name: "Hihi") print([quocnb, hoangls].theMostHandsomer()) // Print: Quoc Nguyen |
Here, with arrays struct conform both to the Developer Developer and the Protocol Handsome, we will write 1 more function to find theMostHansomer. With all such arrays, we can call the .theMostHandsomer function to find the result.
The advantage of using a protocol instead of using classes.
Above, we covered using Protocol oriented programming using simple protocols and extend them with protocol extensions. Protocol extensions are not just extend protocols, but can also be used to provide default variables, default methods for protocols.
Using the protocol with Swift will have advantages compared to using class:
- Protocol can be applied by class, struct and enum. Base class is limited only to the class scope. Only classes can inherit from another class
- While a class can only be inherited from a parent class, a class, struct, and enum can adopt multiple protocols. When a class must inherit a property, or a default method that it uses from a parent class, with the protocol, we can break down the methods and properties to match many classes.
=> The use of Protocol enables us to handle jobs more flexibly with more options.
Conclusion
Above I have introduced through the Orientation Programming Protocol with Swift language. Hopefully it will help you have a closer look at this new writing and apply it in the most proficient way.
Follow Viblo.