Customizing initialization
We want to initialize instances of the Circle
class with the radius value. In order to do so, we can take advantage of customized initializers. Initializers aren't methods, but we will write them with syntax that is very similar to the instance methods. They will use the init
keyword to differentiate from instance methods, and Swift will execute them automatically when we create an instance of a given type. Swift runs the code within the initializer before any other code within a class.
We can define an initializer that receives the radius value as an argument and use it to initialize a property with the same name. We can define as many initializers as we want to, and therefore, we can provide many different ways of initializing a class. In this case, we just need one initializer.
The following lines create a Circle
class and define an initializer within the class body:
class Circle { var radius: Double init(radius: Double) { print("I'm initializing a new Circle instance with a radius value of \(radius).") self.radius = radius } }
The initializer is declared with the init
keyword. The initializer receives a single argument: radius
. The code within the initializer prints a message on the console indicating that the code is initializing a new Circle
instance with a specific radius value. This way, we will understand when the code within the initializer is executed. As the initializer has an argument, we can call it a parameterized initializer.
Then, the following line assigns the radius the Double
value received as an argument to the radius
classes' Double
property. We will use self.radius
to access the radius
property for the instance and radius
to reference the argument. In Swift, the self
keyword provides access to the instance that is created and we want to initialize. The line before the initializer declares the radius
double property. We will dive deep into the proper usage of properties in Chapter 3, Encapsulation of Data with Properties.
The following lines create two instances of the Circle
class named circle1
and circle2
. Note that it is necessary to use the radius
argument label each time we create an instance because we use the previously declared initializer. The initializer specifies radius
as the name of the argument of the Double
type that it requires. When we create an instance, we have to use the same argument name indicated in the initializer declaration, radius
, followed by a colon (:
) and the value we want to pass for the parameter. The first line specifies radius: 25
; therefore, we will pass 25
to the radius parameter. The second line specifies radius: 50
; and therefore, we will pass 50
to the radius
parameter:
var circle1 = Circle(radius: 25) var circle2 = Circle(radius: 50)
When we enter all the lines that declare the class and create the two instances in the Playground, we will see two messages that say "I'm initializing a new Circle instance with a radius value of
" followed by the radius value specified in the call to the initializer of each instance, as shown in the following screenshot:
Each line that creates an instance uses the class name followed by the argument label and the desired value for the radius
class as an argument enclosed in parentheses. Swift automatically assigns the Circle
type for each of the variables (circle1
and circle2
). After we execute the two lines that create the instances of Circle
, we can take a look at the values for circle1.radius
and circle2.radius
in the Playground. We can click on the Quick Look icon and a popup will display the property and its value for the instance. The following screenshot shows the results of inspecting circle1
:
The following line won't allow the Playground to compile the code and will display a build error because the compiler cannot find a parameterless initializer declared in the Circle
class. The specific error message is the following: "Missing argument for parameter 'radius' in call.
" The subsequent screenshot shows the error icon on the left-hand side of the line that tries to create a Circle
instance and the detailed Playground execution error displayed within the Debug area at the bottom of the window:
var circleError = Circle()
Remove the previous line that generated an error and enter the following two lines:
print(circle1.dynamicType) print(circle2.dynamicType)
The Playground will display "Circle\n" as a result for both the lines because both the variables hold instances of the Circle
class, as shown in the following screenshot. The dynamicType
expression allows us to retrieve the runtime type as a value.