Безопасно (или хороший стиль программирования) инициализировать ленивый var с nil vars? - PullRequest
1 голос
/ 27 января 2020

Позвольте мне немного лучше объяснить, что я имею в виду, так как это немного сложно понять.

Я создаю прототип для видеоигры. Каждый уровень наследует основные правила от SKScene, называемого SceneLogic:

class SceneLogic: SKScene, SKPhysicsContactDelegate {
    // Set up the physics, the contacts, touches and so on...
}

class Level1: SceneLogic { }
class Level2: SceneLogic { }

Каждый уровень имеет свой собственный файл .sks, в котором указывается другой значок для отображения в HUD. Чтобы создать своего рода «игровой движок», я подумал инициировать все виды графики внутри класса SceneLogic с помощью lazy var и игнорировать их, если текущему уровню это не нужно.

Позвольте мне объясните на примере

class SceneLogic: SKScene, SKPhysicsContactDelegate {
    // Text, available only for level 1
    private lazy var textTopHUD = childNode(withName: "textTop") as! SKLabelNode

    // Icon, available only for levels 3,4,5
    private lazy var iconBottomHUD = childNode(withName: "iconBottom") as! SKSpriteNode

    // Icon, available only for level 2
    private lazy var iconLeftHUD = childNode(withName: "iconLeft") as! SKSpriteNode


    func initGame(level: Int) {
        switch mode {
            case 1: // Level 1
                textTopHUD.text = "Level 1"
            case 2: // Level 2
                iconLeftHUD.position = ....
        }
    }
}

Факт: для уровня 1 iconBottomHUD равен nil, для уровня 2 textTopHUD равен nil ... но приложение не работает sh, поскольку переменная равна lazy, и она не будет вызываться для некоторых уровней.

Мой вопрос: это хороший стиль программирования? Безопасно ли использовать lazy таким образом?

1 Ответ

1 голос
/ 27 января 2020

Смысл ленивых свойств в том, что он откладывает выполнение кода инициализации. Так что в вашем случае это не имеет значения, так как они на самом деле равны нулю. Таким образом, вы defer init ничего в принципе. Если бы я был тобой, я бы либо сделал его как вычисленную собственность следующим образом:

private lazy var iconBottomHUD: SKSpriteNode = {
      guard let node = childNode(withName: "iconBottom") as? SKSpriteNode else {
          fatalError()
      }
      return node
}

Или сделал бы так, как упомянуто @JavierRivarola, чтобы он был основан на протоколе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...