简体   繁体   中英

Swift- how to initialize struct instance with function or other pattern

This is a dumb example, but I can't think of the right way to avoid repeating myself when I try to initialize my struct instances below. Notice how they get the same initializer (not sure if that's the right phrase), but what would be another way to do this so i'm giving it a function or something like that instead of the same struct.init(...)?

struct InnerSt {
    var a: String
    var b: String
}

var myStructs: [InnerSt] = []

func assignVal() {
    for item in ["dog", "cat", "fish"] {
        let a: String = "I'm a"
        var pets: String
        let inner: InnerSt = InnerSt.init(a: a, b: item)
        switch item {
        case "dog":
            pets = "hairy"
            //print(inner.a + " " + inner.b + " and I'm " + pets)  //this is like what I want to repeatedly do without the repetition
            myStructs.append(inner) //this works nicely but obviously I miss adding the pets variable
        case "cat":
            pets = "furry"
            //print(inner.a + " " + inner.b + " and I'm " + pets)
            myStructs.append(inner)
        case "fish":
            pets = "scaly"
            //print(inner.a + " " + inner.b + " and I'm " + pets)
            myStructs.append(inner)
        default: ()
        }
    }
}

assignVal()
print(myStructs)

To avoid writing a bunch of initialisers you could simply change your implementation as follows:

func assignVal() {
    let a = "I'm a "
    for item in [1, 2] {
        let temp = InnerSt.init(a: a, b: item)
        print(temp)
    }
}

Basically, you do not need to switch because item is being assigned as you loop. It will be assigned the value of 1 on the first iteration and 2 on the second.

The benefits are:

  1. The InnerSt initialiser is written once (even though it is called multiple times).
  2. If your array [1, 2] grows (to say [1, 2, 3] ) you would not need to add new case to your switch .

A few side notes that helped me in the beginning:

  • InnerSt.init(a: a, b: item) can be shortened to InnerSt(a: a, b: item) . Nice for readability.
  • let a: String = "I'm a" can be shorted to let a = "I'm a" . Swift has an excellent type inference system. In this case the complier will infer that a is of type String .
  • innserSt would be better named InnerSt . See Apple's excellent guidelines .

Revision after comments

Playground code:

var petsDescriptions: [String] = [] // array of string descriptions of the animals
var pets = ["dog", "cat", "fish", "deer"] // array of all animals

func assignVal() {

    for pet in pets {

        var surfaceFeeling: String = "" // variable to hold the surface feeling of the pet e.g. "hairy"

        switch pet { // switch on the pet
        case "dog":
            surfaceFeeling = "hairy"
        case "cat":
            surfaceFeeling = "furry"
        case "fish":
            surfaceFeeling = "scaly"
        default:
            surfaceFeeling = "<unknown>"
        }

        let description = "I'm \(surfaceFeeling) and I'm a \(pet)" // construct the string description
        petsDescriptions.append(description) // add it to the storage array
    }
}

assignVal()
print(petsDescriptions)

Console output:

["I\'m hairy and I\'m a dog", "I\'m furry and I\'m a cat", "I\'m scaly and I\'m a fish", "I\'m <unknown> and I\'m a deer"]

Let me know if I answered your question correctly or need to add some more information.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM