Protocol in Swift
1. Introduction Protocol
When it comes to Protocol, we're talking about something abstract. So what is abstraction? Normally, we will know "The cat calls meow
. The dog calls purring
. The duck calls `scooped up ', but I can't say for sure how" pet is going to sound or how to grow up ". So we call it abstraction, although we always know that any animal or bird can be called.
In the programming world, too, people attribute problems / behaviors / attributes that are used in many different types of protocols. To illustrate I will create a CanMakeSound protocol (which can be called) and how to use this protocol.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | protocol CanMakeSound { The func sound () // method in the protocol will not have the body of the body, because it is abstract, there is no record to write anything ? } // protocol can be adopted / implemented by 1 Struct struct Dog: CanMakeSound { // This method sound is required to be defined and has the function body. func sound () { print ("Gau gau") // I know how the dog screams } } // protocol can be used with class Cat class: CanMakeSound { func sound () { print ("Distorted distortion") } } // or Enum is fine enum DogStatus: CanMakeSound { case Normal, BeHungry func sound () { self {switch case .Normal: print ("Beard") case .BeHungry: print ("baby ...") // this place I made myself to illustrate :)) } } } |
Here we know that the protocol can be used by class, struct and even enum. Where the protocol is adopted, where (class / struct / enum) must define and write down details for all the methods that the protocol has. Here we see that the protocol looks similar to the concept of interfaces in other object-oriented languages such as Java, C #, … In Swift protocol, there is not only a method but also a property (spreading Episode 2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | protocol HasName { var name: String {get set} // attributes when used must be allowed to change func fullName () -> String } protocol CanMove { legCount var: Int {get} func move () } // I can adopt many protocols struct Duck: HasName, CanMove { // let name: String will report an error because according to the protocol, this variable must be allowed to change => let let var var name: String let legCount: Int = 2 // here let or var is fine, but this variable can be changed very well fullName func () -> String { return name } func move () { print ("I have (legCount) legs and I can move. Let's move !!!") } } var myDuck = Duck (name: "Donal") print ("Hello, I am (myDuck.fullName ())") myDuck.move () |
2. Mutating methods in the protocol
Mutabling method in protocol means allowing that method to change the intrinsic property (instance property) of Struct or Enum which adopt that protocol. To illustrate I will edit the enum DogStatus above a bit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | CanEat protocol { mutating func eat () } enum DogStatus: CanMakeSound, CanEat { // ... same as the first declaration in vd mutating func eat () { self {switch case .Normal: in ra case .BeHungry: print ("I am eating ... Ok I am full") self = .Normal // updates the value of enum } } } |
3. The init (init) method in the protocol
In Swift we have special methods used to initialize Class, Struct and Enum, without exception (spreading practice 3). The Protocol in Swift can also contain init methods to ensure that anyone who applies it must write details for the initialization function. But for classes, it's a bit different:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | protocol MustHaveInit { init () // init will not need func in front } struct TestStruct: MustHaveInit { var name: String // This is normal, no required keywords init () { name = "Unnamed" } } class B: MustHaveInit { required init () {// This required required keyword } } class C: B { required init () {} // C is the subclass of B, if C has an init function, we still need the required keyword } final class D: MustHaveInit { init () {} // Here it is no longer necessary because D is the final class, meaning there will never be a subclass } |
For the class, we need the required keyword before the initialization function declaration. I will do another lesson in more detail about the initialization methods.
In fact, we will often encounter this keyword when subclass a UIView and rewrite the init function for it. The catcher must have a required method. Something like this:
1 2 3 4 5 6 7 8 | class MyView: UIView { init () {} // This is mandatory if we have rewritten init (), XCode will prompt and add as follows required init? (coder aDecoder: NSCoder) { fatalError ("init (coder :) has not been implemented") } } |
The reason is because UIView itself has a 1 protocol named: NSCoding and in this protocol there is a function public init? (ADecoder coder: NSCoder)
4. Protocol for class-only
In short, the class-only protocol means that it can only be used for the class. By default, Protocol is a value type, and we can turn it into a reference type by:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | protocol ForClassProtocol: class {// pay attention after the Protocol name has ": class" func test () } class TestClass: ForClassProtocol {// OK func test () {} } struct TestStruct: ForClassProtocol {// Error func test () {} } enum TestEnum: ForClassProtocol {// Error func test () {} } |
Protocol: class is also used for the purpose of creating delegates. If we use an object (class instance) to be a delegate, we declare with a weak keyword (to retain retain cycle leading to leak memory). But if we assign a value (enum / struct) and this weak variable, we will get an error because weak variable only goes with reference type (class).
1 2 3 4 5 6 7 8 | protocol DownloaderDelegate: class { func downloaderHasFinished (downloader: Downloader) } class Downloader { weak var delegate: DownloaderDelegate? // Obviously here if we don't have: the class above the protocol will get an error. Removing weak will result in a retaint cycle so we need it } |
5. Optional Protocol Requirements
Now that we know a basic rule when using the protocol, there are many methods in which we have to rewrite many methods when we adopt it. If so, then the protocol will have too many methods, why should I write my tongue too much? @@.
Apple gives us a solution that uses the keyword @objc, which indicates that this protocol can be used with Objective C code, it doesn't sound anything but it really is, regardless of whether we have Whether to use Objective C code in the project. This keyword will also make the protocol become for class-only
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // Before the protocol, there will be @objc @objc protocol OptionalMethodsProtocol { func phảiImplement () tùy chọn func cóNotImplement () } class SomeClass: OptionalMethodsProtocol { @objc func mustImplement () {// The @objc keyword here is required } // We do not need to write the haveNotImplement method because it is optional } Pet struct: OptionalMethodsProtocol {} // error because the protocol is only for class enum Status: OptionalMethodsProtocol {} // error because the protocol is only for class |
So the fact that Protocol in Swift (pure) will not have an optional method … means that if we use Protocol for a struct / enum, how many methods are there to write.
ITZone via IDE Academy