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. }

5. class SomeClass: GenericProtocol {
6. typealias myType = String
7. }
8. class SomeStruct: GenericProtocol {
9. typealias myType = Int
10. }

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.