self vs Self in Swift Programming
Tags: swift, ios
Published: 2024-07-13 15:26:29

In Swift, `self` and `Self` (with a capital 'S') play distinct roles in object-oriented and protocol-oriented programming. They are crucial keywords that ensure clarity, type safety, and facilitate various coding patterns. Let’s dive into their meanings, differences, and practical applications

## self
`self` refers to a class or struct's current instance (object). It distinguishes instance variables or methods from local variables or parameters.

## Self
`Self` (with a capital 'S') refers to the current type itself. It is beneficial in protocols and generic contexts to ensure type safety and clarity.

## Example
```swift
class Person {
    private var name: String
    private var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    func updateAgeWithExactClassType(age: Int) -> Person {
        self.age = age
        return self
    }
    
    func updateAgeWithSelfKeyword(age: Int) -> Self {
        self.age = age
        return self
    }
}

let person = Person(name: "vinay", age: 26)

person.updateAgeWithExactClassType(age: 30)

person.updateAgeWithSelfKeyword(age: 40)
```

1. In the `Person` class example above, `self` is used to refer to the current instance of the class when accessing its properties or methods. Which uses to differ method parameters from instance variables
2. The `updateAgeWithSelfKeyword` method uses `Self` as its return type. This allows the method to return an instance of the same class type (`Person`) or its subclass dynamically, which is useful for method chaining and adhering to the builder pattern

## Benefits of `Self` over exact Class `Person` as return type
### Drawbacks of `updateAgeWithExactClassType`
The `updateAgeWithExactClassType` method explicitly returns `Person`, which limits its usage when subclassing `Person`. If you subclass `Person`, you cannot override this method to return instances of the subclass without changing its return type.

### Advantages of `updateAgeWithSelfKeyword`
The `updateAgeWithSelfKeyword` method uses `Self` as its return type. This means it dynamically resolves to the type of the current instance (`Person` or its subclass). You can override this method in subclasses and have it return instances of those subclasses, maintaining type safety and adhering to the builder pattern.

To understand more let's change the code snippet a little bit.

```swift
class AdvancedPerson: Person {
    
    func extraFunctionality() {
        print("person has super power like avengers")
    }
    
    override func updateAgeWithExactClassType(age: Int) -> Person {
        // some code
        return self
    }
    
    override func updateAgeWithSelfKeyword(age: Int) -> Self {
        // some code
        return self
    }
}

let advancedPerson = AdvancedPerson(name: "IronMan", age: 40)
advancedPerson.updateAgeWithExactClassType(age: 50)
advancedPerson.updateAgeWithSelfKeyword(age: 50)
```

* `updateAgeWithExactClassType` returns `Person` as a type which won't have functionalities of the sub-class `AdvancedPerson` we can't be chaining to access methods of the `AdvancedPerson` class.

![updateAgeWithExactClassType](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u9v55rvuy7y03sauz33g.png)

* `updateAgeWithSelfKeyword` returns `Self` on runtime Swift knows what type should return so that we can access existing functionalities of the sub-class `AdvancedPerson`

![updateAgeWithSelfKeyword](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qobaw42shsgs23b58i6a.png)



## Use of `Self` with protocols
```swift
protocol Address {
    func addAddress(address: String) -> Self
}

class PersonWithAddress: Person, Address {
    private var address: String?
    
    func addAddress(address: String) -> Self {
        self.address = address
        return self
    }
}

let personWithAddress = PersonWithAddress(name: "vinay", age: 26)
personWithAddress.addAddress(address: "India")
```
## Benefits
### self
* **Clarity:** Helps distinguish between instance properties and local variables or parameters within methods.
* **Avoiding Name Conflicts:** Ensures clear referencing of instance properties and methods.

### Self
* **Type Safety:** Guarantees that protocols and generics return or reference the exact type of the conforming or implementing instance.

* **Flexibility:** Supports method chaining and builder pattern, improving code readability and maintainability. Using `Self` allows for returning the exact type without explicitly specifying it, promoting easier code maintenance and adaptation.

## Conclusion
Understanding the distinctions between `self` and `Self` is crucial for writing clear, type-safe, and maintainable Swift code. While `self` refers to the current instance, `Self` ensures consistency in types within protocols and generics. Leveraging these keywords effectively enhances your ability to design robust Swift solutions.

> `self` -> Refers to the current instance (object).
> `Self` -> Refers to the type itself, ensuring type safety and clarity. It simplifies method chaining and conforms to protocols in a flexible manner, improving code maintainability.

[swift playground page](https://github.com/vinaykumar0339/AboutSwift/blob/main/Pages/self_vs_Self.xcplaygroundpage/Contents.swift)