All Categories

Swift 2.x – Promote yourself as a Protocol Oriented Programmer

With the release of swift 2.x some of us might have observed an emphasis from Apple promoting a programmer to become protocol-oriented.

Does it really matter for being a protocol-oriented programmer?

Hopefully once you complete reading this post you would be in a position to make your mind up.

A protocol can be seen as a blueprint of functionality that is expected out of an object that conforms to a protocol in a situation.

An example for the protocol would be an Equatable protocol, a class should conform to the Equatable protocol in case when equality (using ‘==’ operator) for two objects instance need to be checked.

Now lets discuss it all, the good part of using the protocol that Apple has portrayed. Towards the end of this post we would be discussing those items which is not possible to be implemented/used via protocol.

Protocol will Act as a Savior in situation where the type relationship is lost.

The following code depicts tow cases. The situation when Type Relationship being lost is explained in the first section and in the latter section we would look into to the same situation handled by protocol-oriented programmer.

Using Class That showcase situation where Type Relationship is Lost

class AnimalAbstractClass{
func checkIfOlderThan(other:AnimalAbstractClass)->Bool{
fatalError("if not implemented");
}
}
class Dog: AnimalAbstractClass {
var someProperty:Int!
override func checkIfOlderThan(other: AnimalAbstractClass) -> Bool {
return self.someProperty > (other as! Dog).someProperty
}
}
class Cat: AnimalAbstractClass {
var catAge:Int!
override func checkIfOlderThan(other: AnimalAbstractClass) -> Bool {
return self.catAge > (other as! Cat).catAge
}
}

As a thumb rule one should understand that if “ as! aSomeClassInstance” is seen there that implies some type information has been lost.
In the above scenario overhead to implement the checkIfOlderThan function is passed to the subclass

Lets subclass and implement the checkIfOlderThan function as shown in the following case for the class Dog and Cat.

Here from the implementation shown it is clearly visible that other value that is passed as the input parameter for the method signature of checkIfOlderThan function need to be casted to the respective type

other parameter in the checkIfOlderThan method signature is some arbitrary AnimalAbstractClass. We are not even sure that in case of class Dog function implementation the input parameter will have someProperty and can cause potential crash at runtime of the code execution.
Compilation will be successful in the following case. But Runtime error/crash will occur in the code that is written below

var exampleDogVariable = Dog();
exampleDogVariable.checkIfOlderThan(Cat());//Runtime crash

Just take some time to understand why the crash is inevitable in the above line of code.
Thus the above example clearly depicts why class are bad fit for the implementing type relationship in type safe programming language.

Protocol in Swift Provide a Better way to handle above situation

Protocol handles the above situation to prevent the loss of type relation by Self requirement. Let evaluate the following code to understand better.

protocol AnimalAbstractClass {
//This represents a Self requirement
func checkIfOlderThan(other:Self)->Bool
}
class Dog:AnimalAbstractClass {
var someProperty:Int!
func checkIfOlderThan(other: Dog) -> Bool {
return self.someProperty > other.someProperty
}
}
class Cat: AnimalAbstractClass {
var catAge:Int!
func checkIfOlderThan(other: Cat) -> Bool {
return self.catAge > other.catAge
}
}

You would have notice that the method signature of the checkIfOlderThan in the protocol is marked with Self requirement. By marking the method signature with Self requirement, it means that while implementing the protocol, the parameter represented by Self requirement would change to respective parent that which is implementing the protocol

Note : Do not confuse “Self” (s is upper case letter) with the “self”(s is lower case letter)

In the above case we are talking about “Self”(s is upper case letter).

Some Key Point Regarding Self Requirement

  • A Self in protocol act as a place holder and it refers to the type adopting the protocol.
  • A protocol that contains Self somewhere inside can only be used associated with a type that has adopted the protocol.

Now consider the code which previously caused the runtime crash as shown below
var exampleDogVariable = Dog();
exampleDogVariable.checkIfOlderThan(Cat());

  • In this case Compilation Error will be present due to Self Requirement.

This Compilation error here would not sounds great . But if you look closely you would notice that unlike in the former implementation using class where in there should have been a runtime crash, is prevented. The programmer thus is compelled to write safer code using protocol

Ok great next you would have notice would be AnimalAbstractClass is no more a class but a protocol

Protocol Extension

It is possible to provide the function defined in protocol, a default implementation. This is achieved with extensions in swift. We would definitely appreciate this feature. With this we could share a common protocol implementation across different types like struct, class or even enum. The following code depicts the same

protocol Describe {
func describe()
}
extension Describe{
func describe() {
print("\(self.dynamicType)")
//implementation of describe will go here
}
}
class SampleClass:Describe{
}
struct SampleStruct:Describe {
}
enum SampleEnum:Int,Describe {
case One,Two
}

Bang your head: Let do a small exercise. Feel free to use Xcode/Playground

Just take some time to go through the following code. Try to think of a way to call the default implementation of a particular protocol, achieved using protocol extension, to be called while new protocol is defined inheriting the former protocol. This behavior is would look similar to the usage of super keyword while overriding a function in a subclass

protocol ProtocolParent{
func testFunction();
}
extension ProtocolParent{
func testFunction(){
print("hello my super implementaion")
}
}
protocol ProtocolSub:ProtocolParent{
}
extension ProtocolSub{
func testFunction(){
// need to call testFunction implmentaion of the parent SampleProtocolParent as well here. IS this possible thing about this ?
print("hello my current and new implementaion")
}
}

What do you thing is it possible to call the implementation in the inherited child protocol extension? This behavior can be compared to the calling of super method in a subclass.

Protocol Extension Limitations

Interoperability with objective c is not supported to full extend. For example swift protocol extension cannot be called in an objective c class. Extension and protocol cannot be declared together, they have to be separate. The answer to the above question, which looks into the capability of a protocol, is that the protocol is not capable to have such an an implementation in the current version of swift (2.x). The dynamic features of the programming language are not supported to full extend.

Now that we have reached the concluding part of this blog we could conclude by stating that the protocol-oriented programming is really a promising pattern, which one could leverage to bring more abstraction and modularization for the code. Apple is also promoting the developers to think and become a protocol-oriented programmer and let hope Apple will address few of these limitations in the future releases of the swift and support developer to be more protocol oriented.

Keep visiting our site www.acadgild.com for more updates on IOS and other technologies.

Tags

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Related Articles

Close
Close