2

Consider this typical example, sometimes seen in tutorials, etc (even in Apple's code):

protocol Nameable {
     var name: String {get}
}

struct Person : Nameable {
     var name: String
}

My question is, what would be the benefit of this pattern? I can understand it once a function is added to a protocol, but what could be a good application for a protocol with just one or more variables? Why not just add name to each struct and class ?

koen
  • 5,383
  • 7
  • 50
  • 89

3 Answers3

6

Persons are not the only not the only things that you may want to name. Pets have names, roads have names, heck, some people name their cars.

What if we want to name each object in a collection of different objects? If we store those objects in a collection of Any, we don't have any way to guarentee that all objects have names.

This is where protocols come in. By creating a Nameable protocol, we can create a collection of Nameable objects, and be certain that all the objects within are guaranteed to have a name.

Here's an example:

protocol Nameable {
    var name: String {get}
}

struct Person : Nameable {
    let name: String
    let age: Int
    // other properties of a Person
}

struct Pet : Nameable {
    let name: String
    let species: String
    // other properties of a Pet
}

struct Car : Nameable {
    let name: String
    let horsepower: Double
    // other properties of a Car
}

let namableItems: [Nameable] = [
    Person(name: "Steve", age: 21),
    Pet(name: "Mittens", species: "Cat"),
    Car(name: "My Pride and Joy", horsepower: 9000)
]

for nameableItem in namableItems {
    print("\(nameableItem.name) is a \(nameableItem.dynamicType).")
}

Which prints:

Steve is a Person.

Mittens is a Pet.

My Pride and Joy is a Car.

You can try it here.

Community
  • 1
  • 1
Alexander
  • 59,041
  • 12
  • 98
  • 151
  • How does this differentiate from a class and subclass relationship? Why would someone use one or the other? – brandonscript Aug 25 '16 at 20:46
  • 2
    @brandonscript Sometimes it makes sense for multiple types to have some shared functionality, but not be so tightly bound in a class-subclass relationship. For example, many types are `CustomStringConvertible` (have a `description` property) but it doesn't make sense for all of them to subclass a single class. Using a protocol also means you can share functionality between completely different kinds of things (many of which don't have a concept of subclassing)—structs, enums, and classes can all conform to the same protocol. – Jack Lawrence Aug 25 '16 at 20:53
  • 2
    This is more powerful. Inheritance is much more restrictive. If I want my `Car` to be `Nameable` without using a protocol, it would have to be a subclass of an abstract class called `AbstractNameable`. But now my `Car` can no longer be a subclass of `Vehicle`, because Swift (like most languages) doesn't support multiple inheritance. – Alexander Aug 25 '16 at 20:53
  • Great answer and comments!! Nailed it. – brandonscript Aug 25 '16 at 21:22
  • Much clearer now, thanks. I remember reading somewhere that a protocol 'promises functionality', so I didn't understand how that would work without functions. – koen Aug 25 '16 at 22:23
  • 1
    An objects ability to give its answer its name when asked is certainly a type of functionality – Alexander Aug 26 '16 at 02:49
1

Basically you make a promise that your class / struct will contain defined properties.

For structures this is very important because they can't be subclassed.

Also, subclass can only have 1 superclass so you can't create Person who has more than one parent.

I would recommend you to read this article about why use protocols over subclassing and the main purpose of using them:

http://alisoftware.github.io/swift/protocol/2015/11/08/mixins-over-inheritance/

Kristijan Delivuk
  • 1,253
  • 13
  • 24
1

The key to the answer lies in the word protocol.

Protocol is a system of rules that explain the correct conduct and procedures to be followed in formal situations.

That said, when you state that an object (struct, enum, class, ..) must conform to a protocol, you are obliged to respect it. If you do not, Xcode throws an error.

So one of the main, (absolutely not the only utility) is that you can not forget to include the attributes and / or functions in the various objects.

This could be very useful if multiple developers are working on the same code, or simply to avoid potential human error of distraction :) .

Another great advantage of the protocols is that they can be used as types.

Therefore a struct, enum, or different classes, which inherit the same protocol, they can all be traced to the same type.

Andrea Miotto
  • 7,084
  • 8
  • 45
  • 70