The short answer to this question is simple. A method is a function that is associated with a type, that is, a class, a struct, or an enum. This means that every method is a function, but not every function is a method. The long answer is more interesting, though.
An Example
Fire up Xcode and create a playground. Remove the contents of the playground and add an import statement for Foundation.
import Foundation
Let's start simple by defining a function with name sayHelloWorld()
. The sayHelloWorld()
function isn't a method because it is not associated with a type.
import Foundation
func sayHelloWorld() {
print("hello world")
}
Let's now create a method. To create a method, we need a type. We define a struct with name Car
and add a method to Car
with name drive()
.
import Foundation
struct Car {
func drive() {
}
}
drive()
is a method because it is associated with the Car
struct. It is also a function because every method is a function. Because drive()
is a method, we can only invoke drive()
on a Car
object.
struct Car {
func drive() {
}
}
// Create Car
let car = Car()
// Drive Car
car.drive()
Accessing the Object
We now know that there is a subtle difference between functions and methods. There is one other difference that is often overlooked or taken for granted. Let's update the example like this. We print the value of self
in sayHelloWorld()
and drive()
.
import Foundation
func sayHelloWorld() {
print(self)
}
struct Car {
func drive() {
print(self)
}
}
The compiler is confused and throws an error.
The compiler shows us that there is another important difference between functions and methods. The error the compiler throws is obvious. We attempt to access self
from within the function sayHelloWorld()
, but there is no object with name self
in the scope the function is defined in.
What is more curious is that drive()
does have access to an object with name self
. How is that possible? A method always has access to the object on which the method is called. In this example, drive()
is called on a Car
object. The console confirms this.
This opens up some interesting possibilities. Let's update the Car
struct by defining a property, speed
, of type Int
. Swift automatically creates a memberwise initializer that allows us to set the value of the speed
property.
struct Car {
let speed: Int
func drive() {
print(self)
}
}
// Create Car
let car = Car(speed: 20)
// Drive Car
car.drive()
You already know that a method has access to the object on which the method is called. This means that it can also access the properties and methods of that object. Let's update the implementation of the drive()
method by printing the value of the speed
property.
struct Car {
let speed: Int
func drive() {
print("driving at \(self.speed) MPH")
}
}
// Create Car
let car = Car(speed: 20)
// Drive Car
car.drive()
We can take it one step further and omit the self
keyword in the drive()
method because the compiler is smart enough to understand that we attempt to access the speed
property of the Car
object.
struct Car {
let speed: Int
func drive() {
print("driving at \(speed) MPH")
}
}
// Create Car
let car = Car(speed: 20)
// Drive Car
car.drive()
Instance Methods and Type Methods
The drive()
method is an instance method, which means that we can only invoke it on an instance of the type. The compiler throws an error if we attempt to call drive()
on the Car
struct.
Swift also supports type methods in addition to instance methods. A type method is prefixed with the static
or class
keyword. I won't explore this in detail in this post, though. What I want you to remember is that a type method can be called on the type itself. Take a look at this example.
struct Car {
let speed: Int
func drive() {
print("driving at \(speed) MPH")
}
static func createCar() {
print("create a car")
}
}
// Create Car
let car = Car(speed: 20)
// Instance Method
car.drive()
// Type Method
Car.createCar()
In this example, drive()
is an instance method and createCar()
is a type method. There is a lot more to learn about functions in Swift, but I hope you now know what the differences are between functions and methods in Swift.