Declaring new convenience initializers with extensions

So far, we have always worked with one specific type of initializer for all the classes: designated and initializers. These are the primary initializers for a class in Swift, and they make sure that all the properties are initialized. In fact, every class must have at least one designated initializer. However, it is important to note that a class can satisfy this requirement by inheriting a designated initializer from its superclass.

There is another type of initializer known as convenience initializer that acts as a secondary initializer and always ends up calling a designated initializer. Convenience initializers are optional, so any class can declare one or more convenience initializers to provide initializers that cover specific use cases or more convenient shortcuts to create instances of a class.

Now, imagine that we cannot access the code for the previously declared Point3D class. We are working on an app, and we discover too many use cases in which we have to create an instance of a Point3D class based on the values found on any of the following:

  • A tuple with three Int values: (Int, Int, Int)
  • A single Int value that should be used to initialize x, y, and z
  • The x and y properties in a Point2D instance and an Int value that adds the z component

Tip

Swift allows us to add convenience initializers when we extend classes. It isn't possible to add designated initializers using the extend keyword.

The following lines use the extension keyword to add three convenience initializers to the existing Point3D class. The code file for the sample is included in the swift_3_oop_chapter_08_07 folder.

    public extension Point3D { 
      convenience init(tuple: (Int, Int, Int)) { 
        self.init(x: tuple.0, y: tuple.1, z: tuple.2) 
      } 
 
      convenience init(singleValue: Int) { 
        self.init(x: singleValue, y: singleValue, z: singleValue) 
      } 
 
      convenience init(point2D: Point2D, z: Int) { 
        self.init(x: point2D.x, y: point2D.y, z: z) 
      } 
    } 

The convenience keyword before init indicates to Swift that we are declaring a convenience initializer instead of the default designated initializer. The first convenience initializer receives a tuple argument of type (Int, Int, Int) and calls the designated initializer for the class using self.init and providing the values for the three required arguments: x, y, and z. The second convenience initializer receives a singleValue argument of the Int type and calls the designated initializer for the class with singleValue for the three required arguments. The third convenience initializer receives two arguments: point2D and z. The first argument is of the Point2D type, and the second is of type Int. The convenience initializer calls the designated initializer for the class with point2D.x for x, point2D.y for y, and z for z.

The following lines use the recently added convenience initializers to create instances of the Point3D class and print their description. The code file for the sample is included in the swift_3_oop_chapter_08_07 folder.

    var tuple1 = (10, 20, 30) 
    var tuple2 = (5, 10, 15) 
 
    var point3D3 = Point3D(tuple: tuple1) 
    var point3D4 = Point3D(tuple: tuple2) 
    print(point3D3) 
    print(point3D4) 
 
    var point3D5 = Point3D(singleValue: 5) 
    print(point3D5) 
 
    var point2D6 = Point2D(x: 10, y: 11) 
    var point3D6 = Point3D(point2D: point2D6, z: 12) 
    print(point3D6) 

The following lines show the output generated after executing the preceding code:

(x: 10, y: 20, z:30)
(x: 5, y: 10, z:15)
(x: 5, y: 5, z:5)
(x: 10, y: 11, z:12)

The following screenshot shows the results of executing the previous lines in the Playground:

Declaring new convenience initializers with extensions

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.145.128