Search code examples
structparametersswift4naming-conventionsinitializer

(Swift 4.x+) What are the rules for naming parameters in structs’ initializers?


I have been doing an intense - yet basic apparently - study on structs in these last days and one of the things I cannot understand is why one would ever name parameters in an initializer differently from their original name.

I know that is possible, that it is allowed but, in practice, I have always seen shadowing instead.

For example:

struct Person {
    var name: String
    var age: Int

    init(firstName: String, ancientness: Int) {
        self.name = firstName
        self.age = ancientness
    }
}

Apart from the absurd fun one would have in inventing idiotic names, is there a truly practical reason why one would ever do such a thing?

Thank you


Solution

  • The short answer is no. The long answer is when creating a custom structure you don't even have to provide a custom initializer. The struct will provide it for you. Not related to your question but you should always declare your properties as constants. If you need a different value create a new structure with the values updated from the old instance. Just create a "plain" structure:

    struct Person {
        let name: String
        let age: Int 
    } 
    

    This will provide a the default initializer with the following signature:

    Person.init(name: String, age: Int)
    

    If you were gonna provide yourself the same initializer for that structure it would be written as:

    init(name: String, age: Int) { 
        self.name = name
        self.age = age 
    }
    

    the final thoughts

    There is no reason to do such thing. You should keep your initializers names matching the name of the properties that they will be assigned to. The only "advantage" of choosing a different name is not having to explicitly call self inside the initializer.

    In your example it would suffice

    init(firstName: String, ancientness: Int) {
        name = firstName
        age = ancientness
    }
    

    but not on mine

    init(name: String, age: Int) {
        name = name  // Cannot assign to value: 'name' is a 'let' constant
        age = age    // Cannot assign to value: 'name' is a 'let' constant
    }
    

    A Truly practical reason?

    The only one I can see is dropping the self which can already be done 99% of the time already when coding in Swift. I actually like a lot to use the shadowing whenever it is possible in all of my answers. You can see it at this post Swift Array instance method drop(at: Int) where a local var indexshadowing the collection method index<T: Comparable>(_ T, offsetBy: T, limitedBy: T).

    Or at this post Swift: second occurrence with indexOf a classic shadowing example

    var startIndex = self.startIndex
    

    Where you can refer to startIndex local method variable or the collection's instance property adding the self prefix self.startIndex.