Specifying requirements for properties

In Chapter 4, Inheritance, Abstraction, and Specialization, we worked with simple inheritance to specialize animals. Now, we will go back to this example and refactor it to use protocols that allow us to take advantage of multiple inheritance. The decision to work with contract-based programming appears with a new requirement, which is the need to make domestic birds and other domestic animals different from domestic mammals that talk and have a favorite toy. We already had a talk method and a favoriteToy property defined in the DomesticMammal class. However, now that we know how to work with protocols, we don't want to introduce duplicate code, and we want to be able to generalize what is required to be domestic, with a specific protocol for this.

We will define the following six protocols and take advantage of inheritance in protocols; that is, we will have protocols that inherit from other protocols, as follows:

  • AnimalProtocol: This defines the requirements for an animal.
  • DomesticProtocol: This defines the requirements that make an animal be considered a domestic one. However, it doesn't inherit from AnimalProtocol because it just specifies the requirements: anything that can be domestic.
  • MammalProtocol: This defines the requirements for a mammal. The protocol inherits from AnimalProtocol.
  • BirdProtocol: This defines the requirements for birds. The protocol inherits from AnimalProtocol.
  • DogProtocol: This defines the requirements for dogs. The protocol inherits from MammalProtocol.
  • CatProtocol: This defines the requirements for cats. The protocol inherits from MammalProtocol.

In this case, we will use the Protocol suffix to differentiate protocols from classes. All the protocols' names end with Protocol. However, take into account that this is not a common convention in Swift. The recommended convention is to use an ing or able form of a verb, such as Equatable, Comparable, and Locking. However, in this case, the protocol names are best described with a noun and we will have classes with the same names in case we don't add the Protocol suffix. We want to create an Animal class, so we cannot have a protocol with the same name.

The following lines show the code that declares the AnimalProtocol protocol. The code file for the sample is included in the swift_3_oop_chapter_05_12 folder:

    public protocol AnimalProtocol { 
      static var numberOfLegs: Int { get } 
      static var averageNumberOfChildren: Int { get } 
      static var abilityToFly: Bool { get }
  var age: Int { get set } 
      
      static func printALeg() 
      static func printAChild() 
 
      func printLegs() 
      func printChildren() 
      func printAge() 
    } 

The AnimalProtocol protocol requires type properties, stored properties, type methods, and instance methods. First, we will focus on both the type and stored property requirements. The first lines define the type property requirements. We can only use the static keyword to specify a type property requirement, but we can use either static or class when we implement the type property in the class that conforms to the protocol. The usage of the static keyword doesn't have the same meaning that this keyword has when we use it in classes; that is, we can still declare type properties that can be overridden in the classes that conform to the protocol. In fact, this is exactly what we will do when we create the class that conforms to the AnimalProtocol protocol.

In this case, we want the three type properties to be in a read-only format, so we only include the get keyword after the desired type for the type property. The following line shows the type property requirement for numberOfLegs with the get keyword, which makes it a read-only type property:

    static var numberOfLegs: Int { get } 

Tip

We always have to specify the required type in each property requirement.

The protocol defines a stored property requirement named age with both the get and set keywords; therefore, this stored property must be a read-write stored property. Each class that conforms to the protocol can decide whether it is convenient to declare explicit getter and setter methods or just declare a stored property without providing these methods. Both cases are valid implementations because the protocol just requires a read/write stored property. The following line shows the stored property requirement for age:

    var age: Int { get set } 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.178.234