Difference between revisions of "The Basics of Object Oriented Programming in Swift"
(→Calling Methods and Accessing Properties) |
(→Adding Instance Properties to a Class) |
||
Line 66: | Line 66: | ||
Having defined our properties, we can now move on to defining the methods of the class that will allow us to work with our properties while staying true to the data encapsulation model. | Having defined our properties, we can now move on to defining the methods of the class that will allow us to work with our properties while staying true to the data encapsulation model. | ||
− | + | ||
== Defining Methods == | == Defining Methods == | ||
Revision as of 20:18, 1 November 2016
Previous | Table of Contents | Next |
An Overview of Swift Functions and Closures | An Introduction to Swift Inheritance |
Learn SwiftUI and take your iOS Development to the Next Level |
Swift provides extensive support for developing object-oriented iOS applications. The subject area of object oriented programming is, however, large. It is not an exaggeration to state that entire books have been dedicated to the subject. As such, a detailed overview of object oriented software development is beyond the scope of this book. Instead, we will introduce the basic concepts involved in object oriented programming and then move on to explaining the concept as it relates to Swift application development. Once again, whilst we strive to provide the basic information you need in this chapter, we recommend reading a copy of Apple’s The Swift Programming Language book for more extensive coverage of this subject area.
What is an Object?
Objects (also referred to as instances) are self-contained modules of functionality that can be easily used, and re-used as the building blocks for a software application.
Objects consist of data variables (called properties) and functions (called methods) that can be accessed and called on the object or instance to perform tasks and are collectively referred to as class members.
What is a Class?
Much as a blueprint or architect's drawing defines what an item or a building will look like once it has been constructed, a class defines what an object will look like when it is created. It defines, for example, what the methods will do and what the properties will be.
Learn SwiftUI and take your iOS Development to the Next Level |
Declaring a Swift Class
Before an object can be instantiated, we first need to define the class 'blueprint' for the object. In this chapter we will create a bank account class to demonstrate the basic concepts of Swift object oriented programming.
In declaring a new Swift class we specify an optional parent class from which the new class is derived and also define the properties and methods that the class will contain. The basic syntax for a new class is as follows:
class NewClassName: ParentClass { // Properties // Instance Methods // Type methods }
The Properties section of the declaration defines the variables and constants that are to be contained within the class. These are declared in the same way that any other variable or constant would be declared in Swift.
The Instance methods and Type methods sections define the methods that are available to be called on the class and instances of the class. These are essentially functions specific to the class that perform a particular operation when called upon and will be described in greater detail later in this chapter.
To create an example outline for our BankAccount class, we would use the following:
class BankAccount { }
Now that we have the outline syntax for our class, the next step is to add some instance properties to it.
Adding Instance Properties to a Class
A key goal of object oriented programming is a concept referred to as data encapsulation. The idea behind data encapsulation is that data should be stored within classes and accessed only through methods defined in that class. Data encapsulated in a class are referred to as properties or instance variables.
Instances of our BankAccount class will be required to store some data, specifically a bank account number and the balance currently held within the account. Properties are declared in the same way any other variables and constants are declared in Swift. We can, therefore, add these variables as follows:
Learn SwiftUI and take your iOS Development to the Next Level |
class BankAccount { var accountBalance: Float = 0 var accountNumber: Int = 0 }
Having defined our properties, we can now move on to defining the methods of the class that will allow us to work with our properties while staying true to the data encapsulation model.
Defining Methods
The methods of a class are essentially code routines that can be called upon to perform specific tasks within the context of that class.
Methods come in two different forms, type methods and instance methods. Type methods operate at the level of the class, such as creating a new instance of a class. Instance methods, on the other hand, operate only on the instances of a class (for example performing an arithmetic operation on two property variables and returning the result).
Instance methods are declared within the opening and closing braces of the class to which they belong and are declared using the standard Swift function declaration syntax.
Type methods are declared in the same way as instance methods with the exception that the declaration is preceded by the class keyword.
For example, the declaration of a method to display the account balance in our example might read as follows:
class BankAccount { var accountBalance: Float = 0 var accountNumber: Int = 0 func displayBalance() { println("Number \(accountNumber)") println("Current balance is \(accountBalance)") } }
The method is an instance method so it is not preceded by the class keyword.
Learn SwiftUI and take your iOS Development to the Next Level |
class BankAccount { var accountBalance: Float = 0 var accountNumber: Int = 0 func displayBalance() { println("Number \(accountNumber)") println("Current balance is \(accountBalance)") } class func getMaxBalance() -> Float { return 100000.00 } }
Learn SwiftUI and take your iOS Development to the Next Level |
Declaring and Initializing a Class Instance
So far all we have done is define the blueprint for our class. In order to do anything with this class, we need to create instances of it. The first step in this process is to declare a variable to store a reference to the instance when it is created. We do this as follows:
var account1: BankAccount = BankAccount()
When executed, an instance of our BankAccount class will have been created and will be accessible via the account1 variable.
Initializing and Deinitializing a Class Instance
A class will often need to perform some initialization tasks at the point of creation. These tasks can be implemented by placing an init method within the class. In the case of the BankAccount class, it would be useful to be able to initialize the account number and balance properties with values when a new class instance is created. To achieve this, the init method could be written in the class as follows:
class BankAccount { var accountBalance: Float = 0 var accountNumber: Int = 0 init(number: Int, balance: Float) { accountNumber = number accountBalance = balance } func displayBalance() { println("Number \(accountNumber)") println("Current balance is \(accountBalance)") } }
Learn SwiftUI and take your iOS Development to the Next Level |
var account1 = BankAccount(number: 12312312, balance: 400.54)
Conversely, any cleanup tasks that need to be performed before a class instance is destroyed by the Swift runtime system can be performed by implementing the deinitializer within the class definition:
class BankAccount { var accountBalance: Float = 0 var accountNumber: Int = 0 init(number: Int, balance: Float) { accountNumber = number accountBalance = balance } deinit { // Perform any necessary clean up here } func displayBalance() { println("Number \(accountNumber)") println("Current balance is \(accountBalance)") } }
Calling Methods and Accessing Properties
Now is probably a good time to recap what we have done so far in this chapter. We have now created a new Swift class named BankAccount. Within this new class we declared some properties to contain the bank account number and current balance together with an initializer and a method to display the current balance information. In the preceding section we covered the steps necessary to create and initialize an instance of our new class. The next step is to learn how to call the instance methods and access the properties we built into our class. This is most easily achieved using dot notation.
Dot notation involves accessing an instance variable, or calling an instance method by specifying a class instance followed by a dot followed in turn by the name of the property or method:
classInstance.propertyName classInstance.instanceMethod()
For example, to get the current value of our accountBalance instance variable:
var balance1 = account1.accountBalance
Dot notation can also be used to set values of instance properties:
account1.accountBalance = 6789.98
Learn SwiftUI and take your iOS Development to the Next Level |
account1.displayBalance()
Type methods are also called using dot notation, though they must be called on the class type instead of a class instance:
ClassName.typeMethod()
For example, to call the previously declared getMaxBalance type method, the BankAccount class is referenced:
var maxAllowed = BankAccount.getMaxBalance()
Stored and Computed Properties
Class properties in Swift fall into two categories referred to as stored properties and calculated properties. Stored properties are those values that are contained within a constant or variable. Both the account name and number properties in the BankAccount example are stored properties.
Learn SwiftUI and take your iOS Development to the Next Level |
class BankAccount { var accountBalance: Float = 0 var accountNumber: Int = 0; let fees: Float = 25.00 var balanceLessFees: Float { get { return accountBalance - fees } } init(number: Int, balance: Float) { accountNumber = number accountBalance = balance } . . . }
Learn SwiftUI and take your iOS Development to the Next Level |
var balanceLessFees: Float { get { return accountBalance - fees } set(newBalance) { accountBalance = newBalance - fees } }
The new setter takes as a parameter a floating point value from which it deducts the fee value before assigning the result to the current balance property. Regardless of the fact that these are computed properties, they are accessed in the same way as stored properties using dot-notation. The following code gets the current balance less fees value before setting the property to a new value:
var balance1 = account1.balanceLessFees account1.balanceLessFees = 12123.12
Using self in Swift
Programmers familiar with other object oriented programming languages may be in the habit of prefixing references to properties and methods with self to indicate that the method or property belongs to the current class instance. The Swift programming language also provides the self property type for this purpose and it is, therefore, perfectly valid to write code which reads as follows:
class MyClass { var myNumber = 1 func addTen() { self.myNumber += 10 } }
In this context, the self prefix indicates to the compiler that the code is referring to a property named myNumber which belongs to the MyClass class instance. When programming in Swift, however, it is no longer necessary to use self in most situations since this is now assumed to be the default for references to properties and methods. To quote The Swift Programming Language guide published by Apple, “in practice you don’t need to write self in your code very often”. The function from the above example, therefore, can also be written as follows with the self reference omitted:
Learn SwiftUI and take your iOS Development to the Next Level |
func addTen() { myNumber += 10 }
In most cases, use of self is optional in Swift. That being said, one situation where it is still necessary to use self is when referencing a property or method from within a closure expression. The use of self, for example, is mandatory in the following closure expression:
Learn SwiftUI and take your iOS Development to the Next Level |
document?.openWithCompletionHandler({(success: Bool) -> Void in if success { self.ubiquityURL = resultURL } })
It is also necessary to use self to resolve ambiguity such as when a function parameter has the same name as a class property. In the following code, for example, the first println statement will output the value passed through to the function via the myNumber parameter while the second println statement outputs the number assigned to the myNumber class property (in this case 10):
class MyClass { var myNumber = 10 // class property func addTen(myNumber: Int) { println(myNumber) // Output the function parameter value println(self.myNumber) // Output the class property value } }
Whether or not to use self in most other situations is largely a matter of programmer preference. Those who prefer to use self when referencing properties and methods can continue to do so in Swift. Code that is written without use of the self property type (where doing so is not mandatory) is, however, just as valid when programming in Swift.
Summary
Object oriented programming languages such as Swift encourage the creation of classes to promote code reuse and the encapsulation of data within class instances. This chapter has covered the basic concepts of classes and instances within Swift together with an overview of stored and computed properties and both instance and type methods.
Learn SwiftUI and take your iOS Development to the Next Level |
Previous | Table of Contents | Next |
An Overview of Swift Functions and Closures | An Introduction to Swift Inheritance |