# Swift Classes

> An introduction to classes in Swift: defining properties and methods, why classes are reference types, writing initializers with self, and inheritance.

Author: Flavio Copes | Published: 2021-06-10 | Canonical: https://flaviocopes.com/swift-classes/

> This tutorial belongs to the [Swift](https://flaviocopes.com/swift-introduction/) series

Classes are a bit similar to structures, but they have some key differences.

A class is defined using this syntax:

```swift
class Dog {

}
```

Inside a class you can define stored properties:

```swift
class Dog {
    var age = 0
}
```

A class definition defines a **type**. To create a new instance with this type, we use this syntax:

```swift
let roger = Dog()
```

Once you have an instance, you can access its properties using the dot syntax:

```swift
let roger = Dog()
roger.age
```

The same dot syntax is used to update a property value:

```swift
roger.age = 9
```

One big difference is that classes are reference types. Structures (and enumerations) are value types.

This means that assigning a class instance to another variable does not copy the instance. Both variables point to the same instance:

```swift
class Dog {
    var age = 0
}

let roger = Dog()
let syd = roger

roger.age = 9
//syd.age == 9
```

This also means we can define a reference to a class using `let`, and we can change its properties, as you saw in the example above.

We can create instances of classes, and we call them **objects**.

As with structs, classes can have properties, methods, and more.

Contrary to structs, we **must** define an initializer in order to initialize the values when we create an instance:

```swift
class Dog {
    var age : Int
    
    init(age: Int) {
        self.age = age
    }
}

let roger = Dog(age: 9)
```

You can only declare properties without initializing them if you have an initializer.

See the use of `self`. We need it because `age` is both an instance property and the `init(age:)` method parameter. `self.age` references the `age` instance property.

Classes can have **instance methods**: functions that belong to an instance of a class.

```swift
class Dog {
    var age = 8
    var name = "Roger"

    func bark() {
      print("\(name): wof!")
    }
}
```

And we also have **type methods**:

```swift
class Dog {
    var age = 8
    var name = "Roger"

    func bark() {
        print("\(name): wof!")
    }
    static func hello() {
        print("Hello I am the Dog struct")
    }
}
```

Invoked as `Dog.hello()`

One important thing classes allow is inheritance.

A class can inherit all the properties and methods from another class.

Say we have a class `Animal`. Every animal has an age:

```swift
class Animal {
    var age: Int
}
```

Not every animal has a name. Dogs have a name. So we create a `Dog` class extending from `Animal`:

```swift
class Dog: Animal {
    var name: String
}
```

Now we must add an initializer for both classes. In the Dog case, after we do the class-specific initialization, we can call the parent class initializer using `super.init()`:

```swift
class Animal {
    var age: Int
    
    init(age: Int) {
        self.age = age
    }
}

class Dog: Animal {
    var name: String
    
    init(age: Int, name: String) {
        self.name = name
        super.init(age: age)
    }
}

var horse = Animal(age: 8)
var roger = Dog(age: 8, name: "Roger")
```

`Animal` is now a **superclass**, and `Dog` is a **subclass**.

There's more to say about classes, but this is a good introduction.
