Generic Protocols with Associated Type

Learn how to create generic protocol and override associated type

Bob Lee
Bob the Developer
3 min readApr 8, 2017

--

Summer is coming.

Introduction

You’ve started learning Protocols and you’ve got addicted to it. One day, you heard some words like associated type and type eraser. It seems rough and wild. I feel you. So, I wrote this tutorial for you. Let’s get started.

Goals

There are two objectives. First, learn how to create a generic protocol with associatedtype. Second, use where clauses for type constraints similar to that of generics.

Prerequisites

I consider this tutorial as somewhat intermediate-advanced. So, I expect you to be familiar with the topics below.

Intro to Generics, Intro to Protocol Oriented Programming, Closure, Typealias.

If you are not comfortable with the topics above, you might find Learn Swift with Bob useful.

p.s I’m going to be around a while. I plan to cover server-side Swift, RxSwift, Test driven, and all the good stuff. 😃

The Number One Rules

The Swift Programming Language is considered as type-safe. It means, the type must be defined before compiled.

Review

Before we dive into generic protocols, you should be familiar with the following code below.

struct GenericStruct<T> {
var property: T?
}

I could either explicitly state the type of T or let Swift infer based on the value.

let explictStruct = GenericStruct<Bool>() 
// T is Bool
let implicitStruct = GenericStruct(property: "Bob")
// T is String

Keep in mind of the principle that every type must be defined.

Normal Protocol

First, to appreciate generic protocols, let’s look into your/my past. Let’s create a protocol that requires you to add property whose type is String.

Design Protocol

protocol NormalProtocol {
var property: String { get set }
}

Design Class and Conform

class NormalClass: NormalProtocol {
var property: String = "Bob"
}

Sounds good. However, NormalProtocol forces NormalClass to work with String. But, what if you want property to be Int or Bool?

It’s time to introduce Protocol Associated Types. 😎 (I should have a thug-life meme)

Introducing Protocol Associated Types

In generic protocols, to create something like <T> in generics, you need to add associatedtype.

protocol GenericProtocol {
associatedtype myType
var anyProperty: myType { get set }
}

Associated type = type alias + generics

Now, anything that conforms to GenericProtocol must implement anyProperty. However, the type is not defined. Therefore, the class or struct that conforms to the protocol must define it either implicitly or explicitly.

First, let’s create a class SomeClass that conforms to GenericProtocol. We must define myType. Well, there are two ways to define as stated above.

Define Associated Type Implicitly

You may define myType based on the value associated with anyProperty.

class SomeClass: GenericProtocol {
var anyProperty: myType = "Bob"
}

Now, myType has been defined as String based on “Bob”. However, you can let Swift do more guessing as shown below.

class SomeClass: GenericProtocol {
var anyProperty = "Bob" // myType is "String"
}

Is everything okay with you? If so far so good, you can show me some love through ❤️.

Define Associated Type Explicitly

Well, you may also define the associated type, myType by calling typealias. What? Let’s take a look.

class SomeClass: GenericProtocol {
typealias myType = String
var anyProperty: myType = "Bob"
}

If you want to define the associatedtype a.k.a myType, you may use typealias. Of course, it is not necessary since you may define myType implicitly as we’ve seen.

So far, you’ve defined myType as String. Let’s create a struct that conforms to GenericProtocol but myType is Int instead.

struct SomeStruct: GenericProtocol {
var anyProperty = 1996
}

You’ve implicitly stated that myType is Int based on the value of 1996.

If you hear Protocol Associated Types (PATs), it just means generic protocols.

Protocol Extension and Type Constraints

As you already know, Protocol extension is amazing because it provides default implementations without having to define required methods and properties. Let’s review.

Design Extension

extension GenericProtocol {
static func introduce() {
print("I'm Bob")
}
}

Anything that adopts GenericProtocol now contains this magic.

SomeClass.introduce() // I'm Bob
SomeStruct.introduce() // I'm Bob

But all of a sudden, you only want myType as String to have the introduce() method. How do you go about?

I have migrated from Medium to Personal Blog. You can see the rest of the post here.

--

--