Protocol Extension and Type Constraints

Introduction

Welcome to Lesson 2 of Generic Protocols. In Chapter 1, you’ve learned how to add constraints to generic functions with the example of LOL classes. Likewise, you may add constraints to a protocol extension so that the default implementation may only apply to specific classes and structs.

Problem

Limit the scope of Protocol Extension with where and Self

Generic Function - Review

Create a called LOL and create a function called addLOLClassOnly. The parameter of the function only works with value whose type is LOL.

  1. class LOL {}
  2. func addLOLClassOnly<T: LOL>(array: [T]) { }
  3. addLOLClassOnly(array: [LOL()])

Design Protocol

Create a protocol called, GenericProtocol. Create SomeClass and SomeStruct of which conform to the protocol.

  1. protocol GenericProtocol {
  2. associatedtype myType
  3. }
  4. class SomeClass: GenericProtocol {
  5. typealias myType = String
  6. }
  7. class SomeStruct: GenericProtocol {
  8. typealias myType = Int
  9. }

Design Protocol Extension

You may add constraints/conditions to extension by adding a where clause.

Create an extension that its default implementation applies to those whose associated type, myType is String

  1. extension GenericProtocol where myType == String {
  2. static func introduce() {
  3. print("Yo, I'm Bob")
  4. }
  5. }

Classes, structs, and enums with myType as String contain the introduce() static method.

  1. SomeClass.introduce() // "Yo I'm Bob"
  2. SomeStruct.introduce() // Error

You may also add another where clause by adding ,. Let us apply the extension to SomeClass only.

  1. extension GenericProtocol where myType == String, Self == SomeClass {
  2. static func introduce() {
  3. print("Yo, I'm Bob")
  4. }
  5. }

Notes: Self refers to the class/struct/enum that conforms to the protocol.

Design Pre-Defined Associated Type

In the previous lesson, you’ve left associatedtype to be defined by the Self. Yet, you may pre-define the type within the protocol.

  1. protocol FamilyProtocol {
  2. associatedtype familyType = Int
  3. var familyMembers: [familyType] { get set }
  4. }

If you create a struct that conforms to FamilyProtocol, the required property, familyMembers has the type of [Int].

  1. struct NumberFamily: FamilyProtocol {
  2. var familyMembers: [Int] = [1, 3, 4]
  3. }

Source Code

6002_Protocol Extension and Type Constraints.playground

Conclusion

Like generic constraints, you’ve learned how to limit the scope of protocol extensions by implementing where clauses. What a powerful tool. It prevents you from creating bloated objects filled with unnecessary methods and properties.

In the following lesson, you will learn how to override pre-defined associated type.

Note: Learn Swift with Bob is available on Udemy. If you wish to receive a discount link, you may sign up here.