Introduction to Protocols
Protocols define a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. Any type that satisfies the requirements of a protocol is said to conform to that protocol. In addition to specifying requirements that conforming types must implement, you can extend a protocol to implement some of these requirements or to implement additional functionality that conforming types can take advantage of.
Protocol Syntax
1 2 3 |
protocol ProtocolName { // protocol definition goes here } |
Custom types state(Classes, Structs & Enums) can adopt a particular protocol by placing the protocol’s name after the type’s name, separated by a colon, as part of their definition. Multiple protocols can be listed, and are separated by commas:
1 2 3 |
struct AnyStructure: FirstProtocol, SecondProtocol { // structure definition goes here } |
If a class has a superclass, list the superclass name before any protocols it adopts, followed by a comma:
1 2 3 |
class AnyClass: SuperClass, FirstProtocol, SecondProtocol { // class definition goes here } |
1 2 3 |
enum AnyEnum: ProtocolName { // enum definition goes here } |
You might have already seen UIViewController
s implementing UICollectionView
& UITableView
datasource
and delegate
protocols.
1 2 |
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate { } |
Although, the best practice is to group this in a separate extension of ViewController
and implement the protocols.
1 2 3 4 5 6 |
class ViewController: UIViewController { } extension ViewController: UICollectionViewDataSource, UICollectionViewDelegate { //implement protocol methods ands variables here.. } |
Adding Property Requirements
- A protocol can have properties as well as methods that a class, enum or struct conforming to this protocol can implement.
- A protocol declaration only specifies the required property name and type. It doesn’t say anything about whether the property should be a stored one or a computed one.
- A protocol also specifies whether each property must be gettable or gettable and settable.
- Property requirements are always declared as variable properties, prefixed with the
var
keyword. - Gettable and settable properties are indicated by writing
{ get set }
after their type declaration, and gettable properties are indicated by writing{ get }
.
Sample Code:
1 2 3 4 5 6 7 8 9 |
protocol FullName { var fullName: String { get } } struct Lecturer: FullName { var fullName: String } let lecturer = Lecturer(fullName: "John Doe") |
Second Implementation-
1 2 3 4 5 6 7 8 9 |
struct Student: FullNameable { let firstName: String let lastName: String var fullName: String { return "\(firstName) \(lastName)" } } let me = Student(firstName: "John", lastName: "Doe") |
Method Requirements
As mentioned earlier, protocols can have methods as well.
- A protocol can have type methods or instance methods.
- Methods are declared in exactly the same way as for normal instance and type methods but without curly braces or a method body.
- Variadic parameters are allowed.
- Default values are not allowed.
- As with type property requirements, you always prefix type method requirements with the
static
keyword when they are defined in a protocol. This is true even though type method requirements are prefixed with theclass
orstatic
keyword when implemented by a class:
Sample Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
protocol Flyable { func fly() -> String } class Airplane: Flyable { func fly() -> String { return ("Airplane can fly") } } class Bird: Flyable { func fly() -> String { return ("Bird can fly too") } } |
Mutating Method Requirements
Mutating methods are methods that we use on value types like structs and enums. If you define a protocol instance method requirement that is intended to mutate instances of any type that adopts the protocol, mark the method with the mutating
keyword as part of the protocol’s definition. This enables structures and enumerations to adopt the protocol and satisfy that method requirement.
Sample Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
protocol Togglable { mutating func toggle() } enum OnOffSwitch: Togglable { case off, on mutating func toggle() { switch self { case .off: self = .on case .on: self = .off } } } var lightSwitch = OnOffSwitch.off lightSwitch.toggle() // lightSwitch is now equal to .on |
You can know more about protocols from here.
Thank You!!!