Home > Enterprise >  Why is this showing 'Expected 'func' keyword in instance method declaration'
Why is this showing 'Expected 'func' keyword in instance method declaration'

Time:05-17

I'm new to coding and using SwiftUI on Xcode, and I don't see what's wrong with this code:

class NormalSpace {
    var name = ""
    var value = 0
    var rent = 0
    var owned = false
}

var newRoad = NormalSpace()

newRoad.name = "New Road"
newRoad.value = 600
newRoad.rent = 25
newRoad.owned = false

the error 'Expected 'func' keyword in instance method declaration' only shows on the newRoad.name line. The same line also has the error: Invalid redeclaration of 'newRoad'.

What have I done wrong?

CodePudding user response:

In an normal project, this is not valid:

class NormalSpace {
    var name = ""
    var value = 0
    var rent = 0
    var owned = false
}

var newRoad = NormalSpace()

newRoad.name = "New Road"
newRoad.value = 600
newRoad.rent = 25
newRoad.owned = false

You can do that in a playground (where it just runs this code directly), but in an app, code (such as the setting of the properties) belongs in a function or initializer.

That initialization code needs to be placed within some context. Let us imagine that it is inside a struct. But this still is not valid:

class NormalSpace {
    var name = ""
    var value = 0
    var rent = 0
    var owned = false
}

struct Foo {
    var newRoad = NormalSpace()
    
    newRoad.name = "New Road"
    newRoad.value = 600
    newRoad.rent = 25
    newRoad.owned = false
}

The property, newRoad is fine, but the values are not. You need to wrap it inside a func (hence the error) or an init. E.g., this initializes newRoad during the init of the struct:

struct Foo {
    let newRoad: NormalSpace
    
    init() {
        newRoad = NormalSpace()

        newRoad.name = "New Road"
        newRoad.value = 600
        newRoad.rent = 25
        newRoad.owned = false
    }
}

Or you might initialize it in a func:

struct Foo {
    var newRoad: NormalSpace?

    mutating func bar() {
        let road = NormalSpace()

        road.name = "New Road"
        road.value = 600
        road.rent = 25
        road.owned = false

        newRoad = road
    }
}

Or, alternatively, you can initialize this property with a closure (note the extra () at the end):

struct Foo {
    let newRoad: NormalSpace = {
        let road = NormalSpace()
        road.name = "New Road"
        road.value = 600
        road.rent = 25
        road.owned = false
        return road
    }()
}

But the code where you initialize the properties must be placed within some context, so that the compiler knows when those lines of code should be run.


Note, we would generally give NormalSpace a “memberwise initializer”, e.g.:

class NormalSpace {
    let name: String
    let value: Int
    let rent: Int
    let owned: Bool

    init(name: String, value: Int, rent: Int, owned: Bool) {
        self.name = name
        self.value = value
        self.rent = rent
        self.owned = owned
    }
}

Or, if a struct (and we would generally prefer to make our model objects struct value-types rather than class reference-types), this memberwise initializer would be created for you:

struct NormalSpace {
    let name: String
    let value: Int
    let rent: Int
    let owned: Bool
}

Either way, you can then provide all the desired values during initialization, e.g.:

struct Foo {
    let newRoad = NormalSpace(name: "New Road", value: 600, rent: 25, owned: false)
}

Note, that I've removed the “default” values because those really are not appropriate. If you wanted to say that they do not need to be provided, then you would make them “optionals”. But there is generally a big difference between, say, a rent of zero (i.e. it is my grandmother’s house and she's not charging me) and that no rent has been specified. In Swift, we generally avoid using “sentinel” values like "" or 0 for “no value provided”.

Also, now that we have a memberwise initializer, I have also made the properties immutable (let rather than var). If you need to make them mutable (e.g. to let someone change the rent later), fine, revert back to var. But only make properties mutable if you really need to change them later on.

  • Related