Почему это показывает «Ожидаемое ключевое слово func» в объявлении метода экземпляра?

Я новичок в кодировании и использовании SwiftUI в Xcode, и я не вижу, что не так с этим кодом:

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

ошибка «Ожидаемое ключевое слово func в объявлении метода экземпляра» отображается только в строке newRoad.name. В той же строке также есть ошибка: Недопустимое повторное объявление «newRoad».

Что я сделал не так?

Где объявлен этот класс? Внутри другого класса или в новом отдельном файле?

udbhateja 16.05.2022 07:39

Это в его собственном файле

Qwertytops 16.05.2022 07:46

Тогда вы не сможете открыто присвоить значение свойствам. Они должны быть частью структуры/класса и внутри метода (func).

udbhateja 16.05.2022 07:50

Извините, я имел в виду, что это само по себе в структуре. Так это все еще должно быть в func?

Qwertytops 16.05.2022 09:08

Да, у вас не может быть такого кода на верхнем уровне структуры или класса. И, возможно, также не класс, объявленный внутри структуры, хотя технически это разрешено.

Joakim Danielson 16.05.2022 09:27

Внутри struct можно объявлять переменные, константы и функции, но нельзя запускать код, который «висит» внутри. То, что висит внутри struct или class, создается сразу, но если у вас есть код, который нужно запускать последовательно, вы должны использовать функцию/инициализатор.

HunterLion 16.05.2022 09:27
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
74
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В обычном проекте это недопустимо:

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

Вы можете сделать это на игровой площадке (где он просто запускает этот код напрямую), но в приложении код (например, настройка свойств) принадлежит функции или инициализатору.

Этот код инициализации необходимо поместить в некоторый контекст. Давайте представим, что он находится внутри struct. Но это все еще недействительно:

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
}

Свойство newRoad подходит, а значения — нет. Вам нужно обернуть его внутри func (отсюда и ошибка) или init. Например, это инициализирует newRoad во время initstruct:

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

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

Или вы можете инициализировать его в 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
    }
}

Или, в качестве альтернативы, вы можете инициализировать это свойство замыканием (обратите внимание на лишний () в конце):

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

Но код, в котором вы инициализируете свойства, должен быть помещен в некоторый контекст, чтобы компилятор знал, когда следует запускать эти строки кода.


Обратите внимание, что обычно мы даем NormalSpace «членный инициализатор», например:

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
    }
}

Или, если struct (а мы обычно предпочитаем, чтобы наши объекты модели struct имели тип значения, а не class ссылочный тип), для вас будет создан этот поэлементный инициализатор:

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

В любом случае вы можете указать все желаемые значения во время инициализации, например:

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

Обратите внимание, что я удалил значения «по умолчанию», потому что они действительно не подходят. Если бы вы хотели сказать, что их не нужно предоставлять, то вы бы сделали их «необязательными». Но обычно существует большая разница между, скажем, нулевой арендной платой (т. е. это дом моей бабушки, и она не берет с меня плату) и тем, что арендная плата не указана. В Swift мы обычно избегаем использования «дозорных» значений, таких как "" или 0, для «значение не указано».

Кроме того, теперь, когда у нас есть поэлементный инициализатор, я также сделал свойства неизменяемыми (let, а не var). Если вам нужно сделать их изменяемыми (например, позволить кому-то изменить арендную плату позже), хорошо, вернитесь к var. Но делайте свойства изменяемыми только в том случае, если вам действительно нужно изменить их позже.

Спасибо, Роб. Итак, если я хочу создать, скажем, 20 разных экземпляров NormalSpace (я не на 100% придерживаюсь терминологии), последний вариант будет лучшим? А затем, чтобы сослаться на него в другой структуре, это будет Foo.newRoad.owned = false или что-то в этом роде?

Qwertytops 17.05.2022 05:41

Итак, я бы определенно выбрал этот шаблон «членная инициализация». Итак, вопрос в том, что является «моделью» приложения: судя по вашему описанию, это будет массив экземпляров NormalSpace...

Rob 17.05.2022 06:49

В основном думаю Монополия. «Игрок» перемещается по экземплярам NormalSpace и покупает или платит арендную плату. План состоит в том, чтобы использовать struct для инициализации всех различных экземпляров, а затем еще один struct для получения таких значений, как newRoad.rent, и использовать их для изменения количества денег игроков или того, принадлежит ли NormalSpace.

Qwertytops 17.05.2022 09:02

Я действительно не понимаю идею «одной структуры для инициализации экземпляров; другой для извлечения/изменения свойств», но вы можете делать все, что хотите. Но по крайней мере теперь вы видите, как работает инициализация…

Rob 17.05.2022 23:01

Другие вопросы по теме