Protocols are widespread and available in many languages, such as Swift, Objective-C, and Clojure. In order to have a common definition, let's go back to the source, the Swift language guide (https://docs.swift.org/swift-book/LanguageGuide/Protocols.html) :
This first part of the definition is telling us that, contrary to classes or structures, protocols do not provide implementation details, but only the shape. You can think of the protocols as the star, square, and round shaped holes in the popular game for kids. These holes can fit the pieces (instances), as long as the instances have the same shape, but they don't discriminate about the color (different instances).
Let's look at the second part of the definition from the Swift language guide:
This tells us that we can extend protocols. Extending protocols is the action of doing the following:
- Adding new features based on the existing functionalities provided by the protocol
- Implementing requirements so the classes adopting it can share the same implementation
With this second feature, we can implement simple (or complex) algorithms on protocols. These algorithms can then be consumed by any concrete type that conforms to the protocol. Unlike inheritance, where the lineage is vertical—a child only inherits from its parent—protocols provide us with a powerful way to share logic and behaviors horizontally.