Overview
I was trying to get my head around Swift's Protocol Oriented Programming paradigm. As per Apple's WWDC 2015 video https://developer.apple.com/videos/play/wwdc2015/408/ Protocols can achieve everything that inheritance can and also solves the fundamental issue with inheritance.
Though Protocols solves the problem of multiple inheritance by capturing each capability (functionality) as protocol and allowing a class/struct to confirm multiple protocols, I believe Protocols can never replace inheritance for the following reason.
Lets assume I am implementing College/School automation software and there are two Entities, Staff and Principal and lets assume they both take class but principal along with taking class controls the staff.
So I create a protocol which will model the common capability which is taking class. So let's create a protocol.
protocol staffProtocol {
var classHour : Int { get set}
var numberOfClass : Int? { get set }
mutating func doesWork()
}
extension staffProtocol {
mutating func doesWork(){
classHour = 9
numberOfClass = 4
print("Takes calss")
}
}
As Taking class is a common task for both staff and principal so I provided a default extension which provides a implementation for doesWork()
and says takes class.
Now let's write a Staff struct which will confirm to staffProtocol,
struct Staff : staffProtocol {
var classHour: Int = 0
var numberOfClass: Int? = 0
}
Now if I create a staff object as
var staff = Staff()
staff.doesWork()
Everything works absolutely fine, now lets create a Principal struct which will also extend staffProtocol,
struct Principal : staffProtocol {
var classHour: Int = 0
var numberOfClass: Int? = 0
mutating func doesWork() {
print("Also controls other staff")
}
}
Now along with teaching he also controls other staff, so if I override doesWork()
and write "Also controls other staff"
. Now the code in default extension will never be called.
Now in order to provide both teaching capability and controlling capability, I have two methods,
I can create another protocol which will model controlling capability and make principal struct to extend it
Copy the whole code in default extension of staffProtocol
to the principal struct's doesWork implementation and add a line which says Also controls other staff.
Issues:
Issue with Solution 1. We faced the similar issue in Inheritance, when there was need to implement the capabilities which belonged to two different parent classes and as multiple inheritance was not allowed we used to create the capability as a component and add the component as a property to parent class so that we can achieve multiple capability without having to implement multiple inheritance (which is anyway not allowed). But apple says its too much of code and absolutely not essential.
Even with protocol oriented programming if I have to implement each capability as a protocol isn't am running into same nook of the problem? Rather than creating a capability as a component am I not creating it as a protocol? How is that protocol adding benefit here?
Issues with solution 2. Because I can't call the default extension of the protocol and end up writing the whole code in struct specific implementation again, Haven't I ended up in code duplication issue which is the common problem which inheritance tried solving in a very first place?
Question
Question am trying to find solution is not how can I solve it? There are 100 ways to solve each problem, all I am trying to ask is,
Is protocol programming really an alternative to Object oriented programming?
Is protocol really a replacement to inheritance ? If yes at what cost? Writing simply super.doesWork() was clear or writing a separate protocol for each capability?
I might have completely misunderstood the concept of Protocol Oriented Programming, please help me understand the same.
Protocol-Oriented Programming is a new programming paradigm ushered in by Swift 2.0. In the Protocol-Oriented approach, we start designing our system by defining protocols. We rely on new concepts: protocol extensions, protocol inheritance, and protocol compositions. The paradigm also changes how we view semantics.
Why Protocol-Oriented Programming? Protocols allow you to group similar methods, functions and properties. Swift lets you specify these interface guarantees on class , struct and enum types. Only class types can use base classes and inheritance.
You can create objects from classes, whereas protocols are just type definitions. Try to think of protocols as being abstract definitions, whereas classes and structs are real things you can create.
calls interfaces "protocols." When they say "protocol oriented" they mean programming using interfaces instead of inheritance. Objective-C allows you to define protocols, which declare the methods expected to be used for a particular situation. Protocols are implemented in the classes conforming to the protocol.
(Very late to the party though. I came across this thread after having some beginning level knowledge about the POP
)
Suppose, you are going to write some bird classes. Like:
Some of them can fly and some can't. In OOP, you have various options to design. Most commons are:
You design a base class Fly, then by subclassing it you design Bird and then you use this Bird as the base class for all the bird classes in the question. Override the flying/not flying behavior for each bird type.
Or, you can have a base class Fly, you subclass it for FlyingBird. And then you have another base class NotFlyingBird. After that you subclass these two classes according to your need.
The above approaches work. But you see for the case 1:
Every time you create a new bird, you are also inheriting some capabilities that you don't need maybe.
And in the case 2:
You create two separate base class of your need! What if you need to write something common for FlyingBird and NotFlyingBird? You will probably end up changing your mind to use the approach 1 here.
And lastly, every time you change your mind in later time you end up inheriting from different base class. Or just adding all of the behaviors in a god-like class
Now see, how you can design this with POP
approach.
protocol Flyable { ... }
protocol Bird { ... }
struct Flappy: Bird, Flyable { ... } //it's a bird & can fly
struct SwiftBird: Bird, Flyable { ... } //it's a bird & can fly
struct Stork: Bird, Flyable { ... } //it's a bird & can fly
struct Penguin: Bird { ... } //it's a bird but can't fly
struct Ostrich: Bird { ... } //it's a bird but can't fly
struct Eagle: Bird, Flyable { ... } //it's a bird & can fly
See! how POP
really shine? So, it’s a good thing you didn’t take the inheritance approach, and make all birds flyable after all!
With protocol oriented programming you just don't magically inherit everything from the Super class. You are enforcing to provide their own. With this approach, you are adding behaviors. So you can keep out the burden off your shoulder.
If you need anything very new, you just add to them and not enforcing every other one to have that very new thing without their actual consent.
This Introducing Protocol-Oriented Programming in Swift 3 article from RayWenderlich may even lighten up you a bit more.
You might even have a look at this answer from a different thread.
Let's answer your trailing questions in short:
->
Not always. But it has it's shine.
->
Again, No. But!! If you are designing from the scratch it's worth it to give this idea a shot.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With