Why swift is called Protocol Oriented language or Protocol Oriented Programming ?
Protocol Oriented Programming: This design approach works, but does come with some drawbacks. For example, if you add the ability to create machines that also require gas, birds that fly in the background, or anything else that may want to share game logic, there isn’t a good way to separate the functional components of vehicles into something reusable.
This scenario is where protocols really shine.
Swift has always let you specify interface guarantees on existing class, struct and enum types using protocols. This lets you interact with them generically. Swift 2 introduced a way to extend protocols and provide default implementations. Finally, Swift 3 improves operator conformance and uses these improvements for the new numeric protocols in the standard library.
Protocol are extremely powerful and can transform the way you write code. In this tutorial, you’ll explore the ways you can create and use protocols, as well as use protocol-oriented programming patterns to make your code more extensible.
You’ll also see how the Swift team was able to use protocol extensions to improve the Swift standard library itself, and how it impacts the code you write.
Before we start writing code, lets create a class diagram that shows our design. I usually start off by doing a very basic diagram that simply shows the classes themselves without much detail. This helps me picture the class hierarchy in my mind. The following diagram shows the class hierarchy for our Object-Oriented design:
This diagram shows that we have one superclass named Animal and two subclasses named Alligator and Lion. We may think that, with the three categories, we would need to create a larger class hierarchy where the middle layer would contain the classes for the Land, Air and Sea animals however that is not possible with our requirements. The reason this is not possible is because animal types can be members of multiple categories and with a class hierarchy each class can have only one super class. This means that our Animal super class will need to contain the code required for each of the three categories. Lets take a look at the code for the Animal super class.
As we can see in these classes we override the functionality needed for each animal. The Lion class contains the functionality for a land animal and the Alligator class contains the functionality for both a land and sea animal. Since both class have the same Animal superclass we can use polymorphism to access them through the interface provided by the Animal superclass. Lets see how we would do this.
How we designed the animal types here would definitely work but there are several drawbacks to this design. The first drawback is the large monolithic Animal superclass. For those that are familiar with designed characters for video games you probably realize how much functionality is actually missing form the Animal superclass and it’s subclasses. This is on purpose so we can focus on the design and not all of the functionality. For those who are not familiar with designed characters for video games, trust me when I say that this class will get much bigger when we add all of the functionality needed.
Another drawback is not being able to define constants in the superclass that the subclasses can set. We could define an initiator in the superclass that would set all of the constants however the initiator would become pretty complex and that is something we would like to avoid. The builder pattern could help us with the initiation but as we are about to see, a protocol oriented programming design would be even better.
One final drawback that I am going to point out is the use of flags (landAnimal, seaAnimal and airAnimal properties) to define the type of animal. If we accidently set these flags wrong then the animal will not behave correctly. As an example, if we set the seaAnimal flag rather than the landAnimal flag in the Lion class then the lion would not be able to move or attack on land. Trust me it is very easy even for the most experience developer to set flags like these wrong.
Now lets look at how we would define this same functionality in a Protocol-Oriented way.
Protocol Oriented Programming or Protocol Oriented Langauge Design
Just like with the Object-Oriented design, we will want to start off with a type diagram that shows the types needed to create and the relationships between them. The following diagram shows our Protocol Oriented programming design.
As we can see our POP (Protocol Oriented Programming) design is different from our OOP design. In this design we use three techniques that make POP significantly different from OOP. These techniques are protocol inheritance, protocol composition and protocol extensions.
Protocol inheritance is where one protocol can inherit the requirements from one or more other protocols. In our example the LandAnimal, SeaAnimal and AirAnimal protocols will inherit the requirements of the Animal protocol.
Protocol composition allows types to conform to more than one protocol. This is one of the many advantages that POP has of OOP. With OOP a class can have only one superclass which can lead to very monolithic superclasses as we just saw. With POP we are encouraged to create multiple smaller protocols with very specific requirements. Protocol extensions are arguably one of the most important parts of the protocol-oriented programming paradigm. They allow us to add functionality to all types that conform to a given protocol. Without protocol extensions if we had common functionality that was needed for all types, that conformed to a particular protocol, then we would of had to add that functionality to each type. This would lead to large amounts of duplicate code and that would not be ideal to say the least.
Lets look at how this design works. We will start off by defining our Animal protocol. Notice that we specify that the Lion type conforms to the LandAnimal protocol while the Alligator type conforms to both the LandAnimal and SeaAnimal protocols. Having a single type that conforms to multiple protocols is called protocol composition and is what allows us to use smaller protocols rather than one giant monolithic superclass as in the OOP example.
Both the Lion and Alligator types originate from the Animal protocol thereforel we can still use polymorphism as we did in the OOP example where we use the Animal type to store instances of the Lion and Alligator types. Lets see how this works:
seeing some of the advantages that protocol-oriented programming has over object- oriented programming, we may think that protocol-oriented programming is clearly superior to object-oriented programming. However, this assumption may not be totally correct.
Object-oriented programming has been around since the 1970s and is a tried and true programming paradigm. Protocol-oriented programming is the new kid on the block and was designed to correct some of the issues with object-oriented programming. I have personally used the protocol-oriented programming paradigm in a couple of projects and I am very excited about its possibilities.
Object-oriented programming and protocol oriented programming have similar philosophies like creating custom types that model real-world objects and polymorphism to use a single interface to interact with multiple types. The difference is how these philosophies are implemented.
To me, the code base in a project that uses protocol-oriented programming is much safer and easier to read and maintain as compared to a project that uses object-oriented programming. This does not mean that I am going to stop using object-oriented programming all together. I can still see plenty of need for class hierarchy and inheritance.