What a class is
A class is a blueprint for objects. It lists the data every object carries, called properties, and the actions every object can perform, called methods. An object, or instance, is one concrete thing made from that blueprint: one employee named Andrew who is 30, another named Mary who is 25. You define the blueprint once and create as many instances as you need.
The simplest class is an empty one, created by calling its name like a function. Swift has no new keyword:
class Employee {
}
let employee = Employee()
Properties
A property is a variable that belongs to each instance. Declare it with var for a changeable value or let for a fixed one, and give it a type. Read and change it with the dot operator:
class Employee {
var name: String = ""
var age: Int = 0
}
let emp1 = Employee()
emp1.name = "Andrew"
let emp2 = Employee()
emp2.age = 40
print(emp1.name, emp1.age, emp2.name.isEmpty, emp2.age)
Andrew 0 true 40
Each instance has its own copy of the properties, so changing emp1.name leaves emp2.name as it was. Notice that emp1 is a let and yet its name changes. A class is a reference type: the constant holds a reference to the object, and the object's own var properties can change. What the constant forbids is pointing emp1 at a different object. Assigning an instance to a second variable gives you another reference to the same object, not a copy.
Initializers
Setting properties one by one after creation is clumsy and easy to forget. An initializer, written init, sets them up when the object is created. Swift requires every stored property to have a value by the time init finishes, which is why a property with no default value is allowed as long as init assigns it:
class Employee {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
let emp1 = Employee(name: "Andrew", age: 30)
print(emp1.name, emp1.age)
Andrew 30
Inside init, the parameter name hides the property of the same name. self refers to the object being built, so self.name = name stores the parameter in the property. In Swift, parameter names are also labels at the call site: Employee(name: "Andrew", age: 30). Put _ in front of a parameter to drop its label, so init(_ title: String) is called as Job("Software Engineer"). Calling it with a label anyway is a compile error ("extraneous argument label").
Methods
A method is a function declared inside the class. It runs on one instance and can use that instance's properties by name. Writing self. is optional unless a parameter has the same name:
class Employee {
var name: String
init(name: String) { self.name = name }
func greet() {
print("Hi, I am \(name)")
}
}
Employee(name: "Mary").greet()
Hi, I am Mary
The text \(name) is string interpolation: Swift evaluates the expression inside the parentheses and inserts it into the string.
The exercise, step by step
The task is to build a Job class and use it in mainFunction.
- Declare the class.
class Job { }at the top of the file. - Add the property.
var title: Stringstores the job's title. It needs no default, because the initializer will always set it. - Add the initializer.
init(_ title: String)takes one parameter without a label, so a job is created withJob("Software Engineer"). - Store the value. Inside
init,self.title = titlecopies the parameter into the property. - Declare the method.
func hireMe()takes no parameters. - Print the message. Inside
hireMe,print("You're hired as a \(title)")uses interpolation. The propertytitleneeds noself.. - Create the object. In
mainFunction,let job = Job("Software Engineer"). - Call the method.
job.hireMe()prints the message.
class Job {
var title: String
init(_ title: String) {
self.title = title
}
func hireMe() {
print("You're hired as a \(title)")
}
}
class Solution {
func mainFunction() {
let job = Job("Software Engineer")
job.hireMe()
}
}
Calling mainFunction() prints You're hired as a Software Engineer. Changing job.title first changes the message, because title is a var.
Common mistakes
- Leaving a property unset. If
initnever assignstitle, the compiler reports "return from initializer without initializing all stored properties". - Forgetting
self.when names clash. Without it,title = titlerefers to the parameter on both sides, and the compiler rejects it because a parameter is a constant. - Using a label where there is none.
Job(title: "x")fails when the initializer declares_ title. - Expecting a copy.
let b = afor a class instance makesbandathe same object.
Key takeaways
- A class defines properties and methods; instances are made by calling the class name with no
new. initmust give every stored property a value, andselfnames the current object.- Parameter names are labels at the call site unless you write
_. - Classes are reference types, so assigning an instance shares it.
