How to define Optional Methods in the Swift Protocol?

This article will explain to you how to define optional methods in the protocol.

Before diving into making optional methods in the protocol, you will first learn what a protocol is and how to declare one in Swift.

What is The Protocol?

A protocol is a type that defines a group of methods or properties. Basically, you can define a blueprint of methods to specify behavior. A protocol is similar to interfaces in other programming languages.

Syntax

Here is the syntax of a simple protocol in Swift ?

protocol <protocol_name> {
   // Properties
   // Methods
}

Basic Example

In this example, you will create a protocol called Person along with some properties and methods related to a person entity.

Here is an example of a person protocol in Swift ?

<div class="code-mirror  language-swift" contenteditable="plaintext-only" spellcheck="false" style="outline: none; overflow-wrap: break-word; overflow-y: auto; white-space: pre-wrap;"><span class="token keyword">protocol</span> <span class="token class-name">PersonProtocol</span> <span class="token punctuation">{</span>

   <span class="token comment">// Properties</span>
   <span class="token keyword">var</span> id<span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">{</span> <span class="token keyword">get</span> <span class="token keyword">set</span> <span class="token punctuation">}</span>

   <span class="token comment">// Methods</span>
   <span class="token keyword">func</span> <span class="token function-definition function">fullName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-></span> <span class="token class-name">String</span>
<span class="token punctuation">}</span>
</div>

The PersonProtocol defines a property called id with getter and setter methods, and a method called fullName() that returns a string. To conform to this protocol, a type must implement both of these requirements.

Here is an example of a struct that conforms to the PersonProtocol protocol ?

<div class="code-mirror  language-swift" contenteditable="plaintext-only" spellcheck="false" style="outline: none; overflow-wrap: break-word; overflow-y: auto; white-space: pre-wrap;"><span class="token keyword">struct</span> <span class="token class-name">Employee</span><span class="token punctuation">:</span> <span class="token class-name">PersonProtocol</span> <span class="token punctuation">{</span>
   <span class="token keyword">let</span> firstName<span class="token punctuation">:</span> <span class="token class-name">String</span>
   <span class="token keyword">let</span> lastName<span class="token punctuation">:</span> <span class="token class-name">String</span>
<span class="token punctuation">}</span>
</div>

Now, if you compile the above code, you must get an error message like the following ?

Type 'Employee' does not conform to protocol 'PersonProtocol'

The error message clearly states that the protocol called PersonProtocol does not conform properly. This error is coming because you have not implemented the required methods and properties in the Employee type.

This means you have to fulfill all the implementation requirements to comply with the protocol. You can change the code to look like this ?

<div class="code-mirror  language-swift" contenteditable="plaintext-only" spellcheck="false" style="outline: none; overflow-wrap: break-word; overflow-y: auto; white-space: pre-wrap;"><span class="token keyword">struct</span> <span class="token class-name">Employee</span><span class="token punctuation">:</span> <span class="token class-name">PersonProtocol</span> <span class="token punctuation">{</span>

   <span class="token comment">// MARK: - Properties</span>
   <span class="token keyword">let</span> firstName<span class="token punctuation">:</span> <span class="token class-name">String</span>
   <span class="token keyword">let</span> lastName<span class="token punctuation">:</span> <span class="token class-name">String</span>

   <span class="token comment">// MARK: - PersonProtocol</span>
   <span class="token keyword">var</span> id<span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token operator">=</span> <span class="token function">UUID</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>uuidString

   <span class="token keyword">func</span> <span class="token function-definition function">fullName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> firstName <span class="token operator">+</span> <span class="token string-literal"><span class="token string">" "</span></span> <span class="token operator">+</span> lastName
   <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</div>

Notice here that whatever you have declared in the defined protocol must be implemented in the conforming type. But sometimes, it is not necessary to implement all the methods in the type.

Protocols can also specify optional requirements, which are methods or properties that a conforming type can choose to implement. Protocol Extension is the preferred way to mark methods or properties as optional.

Protocol extension is a way to provide the default implementation of methods or properties to make them optional. Despite the default implementation, a type conforming to the protocol can provide its own implementation of optional methods.

Let's look at an example to provide a default implementation of the protocol ?

Let?s create another protocol like the following ?

<div class="code-mirror  language-swift" contenteditable="plaintext-only" spellcheck="false" style="outline: none; overflow-wrap: break-word; overflow-y: auto; white-space: pre-wrap;"><span class="token keyword">protocol</span> <span class="token class-name">Stack</span> <span class="token punctuation">{</span>
   <span class="token keyword">var</span> elementCount<span class="token punctuation">:</span> <span class="token class-name">Int</span> <span class="token punctuation">{</span>
      <span class="token keyword">get</span>
   <span class="token punctuation">}</span>
<span class="token keyword"><font color="#000000">   </font>mutating</span> <span class="token keyword">func</span> <span class="token function-definition function">push</span><span class="token punctuation">(</span><span class="token omit keyword">_</span> element<span class="token punctuation">:</span> <span class="token class-name">Int</span><span class="token punctuation">)</span>
   <span class="token keyword">mutating</span> <span class="token keyword">func</span> <span class="token function-definition function">pop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-></span> <span class="token class-name">Int</span><span class="token operator">?</span>
<span class="token punctuation">}</span>
</div>

In the above protocol, we define Stack with some properties and methods. Currently, all the methods are required to implement as below ?

<div class="code-mirror  language-swift" contenteditable="plaintext-only" spellcheck="false" style="outline: none; overflow-wrap: break-word; overflow-y: auto; white-space: pre-wrap;"><span class="token keyword">struct</span> <span class="token class-name">StackContainer</span><span class="token punctuation">:</span> <span class="token class-name">Stack</span> <span class="token punctuation">{</span>

   <span class="token keyword">private</span> <span class="token keyword">var</span> items<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token class-name">Int</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>

   <span class="token keyword">var</span> elementCount<span class="token punctuation">:</span> <span class="token class-name">Int</span> <span class="token punctuation">{</span>
      items<span class="token punctuation">.</span>count
   <span class="token punctuation">}</span>

   <span class="token keyword">mutating</span> <span class="token keyword">func</span> <span class="token function-definition function">push</span><span class="token punctuation">(</span><span class="token omit keyword">_</span> element<span class="token punctuation">:</span> <span class="token class-name">Int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      items<span class="token punctuation">.</span><span class="token function">insert</span><span class="token punctuation">(</span>element<span class="token punctuation">,</span> at<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">)</span>
   <span class="token punctuation">}</span>

   <span class="token keyword">mutating</span> <span class="token keyword">func</span> <span class="token function-definition function">pop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-></span> <span class="token class-name">Int</span><span class="token operator">?</span> <span class="token punctuation">{</span>
      items<span class="token punctuation">.</span><span class="token function">removeLast</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
   <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</div>

Now, you don't want to implement the pop() method in the type. So you can provide a default implementation of this method like the below ?

<div class="code-mirror  language-swift" contenteditable="plaintext-only" spellcheck="false" style="outline: none; overflow-wrap: break-word; overflow-y: auto; white-space: pre-wrap;"><span class="token keyword">extension</span> <span class="token class-name">Stack</span> <span class="token punctuation">{</span>
   <span class="token keyword">mutating</span> <span class="token keyword">func</span> <span class="token function-definition function">pop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-></span> <span class="token class-name">Int</span><span class="token operator">?</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token nil constant">nil</span>
   <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</div>

Implementation of type conformance might look like this ?

<div class="code-mirror  language-swift" contenteditable="plaintext-only" spellcheck="false" style="outline: none; overflow-wrap: break-word; overflow-y: auto; white-space: pre-wrap;"><span class="token keyword">struct</span> <span class="token class-name">StackContainer</span><span class="token punctuation">:</span> <span class="token class-name">Stack</span> <span class="token punctuation">{</span>
   <span class="token keyword">private</span> <span class="token keyword">var</span> items<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token class-name">Int</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
   <span class="token keyword">var</span> elementCount<span class="token punctuation">:</span> <span class="token class-name">Int</span> <span class="token punctuation">{</span>
      items<span class="token punctuation">.</span>count
   <span class="token punctuation">}</span>
   <span class="token keyword">mutating</span> <span class="token keyword">func</span> <span class="token function-definition function">push</span><span class="token punctuation">(</span><span class="token omit keyword">_</span> element<span class="token punctuation">:</span> <span class="token class-name">Int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      items<span class="token punctuation">.</span><span class="token function">insert</span><span class="token punctuation">(</span>element<span class="token punctuation">,</span> at<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">)</span>
   <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</div>

As you can see, the pop() method is no longer required to implement in the type.

Conclusion

The ability to extend an existing protocol with default behaviors is quite powerful. This allows protocols to grow and be extended without having to worry about breaking the compatibility of existing code.

Updated on: 2023-01-03T10:25:17+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements