Showing posts with label protocols. Show all posts
Showing posts with label protocols. Show all posts

Tuesday, August 28, 2018

Protocol Extensions for Default and Convenient API


In this tutorial, let’s see how protocol extensions can be used as default and convenient API.

I am taking a Movable protocol which is having a move method.


     
  protocol Movable {
    func move(at minimumSpeed: Float)
  }


I am creating a class called Car which confirms to Movable protocol.


     
  class Car: Movable {
    
   }


This gives a build error.



We need to implement move method as Car is confirming to Movable.

Instead of this forced implementation, using protocol extensions, we can write default implementation.


     
  extension Movable {

    func move(at minimumSpeed: Float) {
      print("Moving @ \(minimumSpeed) MPH")
    }

  }

  let car = Car()
  car.move(at: 40.0)


This is how we can leverage protocol extensions for default implementations.

Now, What If I don’t want to mention the speed every time. I need to go with minimum speed 40.0 as default speed.

This can also be done using the protocol extensions, by having default value for minimumSpeed.


     
  extension Movable {

 func move(at minimumSpeed: Float = 40.0) 
  {
     print("Moving @ \(minimumSpeed) MPH")
  }

 }

 let car = Car()
 car.move()


Simple and useful. Isn’t it?

Hope this post is useful. Feel free to comment incase of any queries.


Thursday, July 12, 2018

Swift Protocol Extensions


Protocol extensions is one of the beautiful features of Swift language.

Let’s see the usefulness with a use case.

I have a Logger protocol which is having simple log function which takes string to be logged and logs it.


       
 protocol Logger {
    func log(message: String)
 }



I am taking 3 service classes which has to confirm to this Logger protocol for logging service errors.

       
 class FacebookServices: Logger {
    func log(message: String) {
        print("Facebook - \(message)")
    }
 }

 class TwitterServices: Logger {
    func log(message: String) {
        print("Twitter - \(message)")
    }
 }

 class InstagramServices: Logger {
    func log(message: String) {
        print("Instagram - \(message)")
    }
 }



All the 3 classes are confirming to Logger protocol and implemented interface method log.

Now, What If we need log a generic error like "Service Unavailable”. 

We need to write that in all the 3 classes or we need to take a base class and keep the logGenericError method there.

       
 class FacebookServices: Logger {
    func log(message: String) {
        print("Facebook - \(message)")
    }
    
    func logGenericError() {
        print("Service unavailable!")
    }
 }

 class TwitterServices: Logger {
    func log(message: String) {
        print("Twitter - \(message)")
    }
    
    func logGenericError() {
        print("Service unavailable!")
    }
 }

 class InstagramServices: Logger {
    func log(message: String) {
        print("Instagram - \(message)")
    }
    
    func logGenericError() {
        print("Service unavailable!")
    }
 }



Instead of this, We can extend the Logger protocol and keep our convenient API there which allows all the classes confirming to the portal can access that extension.

       
 extension Logger {
    func logGenericError() {
        print("Service unavailable!")
    }
 }

 let twitter = TwitterServices()
 let facebook = FacebookServices()

 twitter.log(message: "404")
 twitter.logGenericError() // Service unavailable!

 twitter.log(message: "500")
 twitter.logGenericError()  // Service unavailable!




Easy and very useful Right?

We can customise the logGenericError() If a service needs like shown below.

       
 class InstagramServices: Logger {
    func log(message: String) {
        print("Instagram - \(message)")
    }
    func logGenericError() {
        print("Please try later!")
    }
 }

 let instagram = InstagramServices()
 instagram.logGenericError() // Please try later!



Go with Protocol extensions in such use cases instead of going for base classes.

Hope this post is useful. Feel free to comment incase of any queries.