Вызов метода экземпляра во время инициализации в Swift

Я новичок в Swift и хотел бы инициализировать переменную-член объекта, используя метод экземпляра, подобный этому:

class MyClass {
  var x: String
  var y: String

  func createY() -> String {
    self.y = self.x + "_test" // this computation could be much more complex
  }

  init(x: String) {
    self.x = x
    self.y = self.createY()
  }     
}

В принципе, вместо того, чтобы вставлять весь код инициализации в метод init, я хочу извлечь код инициализации y выделенному методу createY и вызвать этот метод экземпляра createY в init. Однако компилятор Swift (компилятор Swift 1.2 в Xcode 6.3 beta) жалуется:

использование 'self' в вызове метода 'xxx' перед super.init инициализировать self

Здесь 'xxx' - это имя метода экземпляра (createY).

Я могу понять, что компилятор Swift жалуется, и потенциальную проблему, которую он хочет решить. Однако я не знаю, как это исправить. Что должно быть правильным способом в Swift для вызова другого метода инициализации кода экземпляра в init?

В настоящее время я использую следующий трюк, поскольку работаю, но я не думаю, что это идиоматическое решение этой проблемы (и это обходное решение требует, чтобы y был объявлен с использованием var вместо let, что заставляет меня тоже чувствую себя неловко):

init(x: String) {
  self.x = x
  super.init()
  self.y = createY()
} 

Любые комментарии приветствуются. Спасибо.

Ответ 1

Преобразовать createY() в глобальную или классную функцию, которая принимает x в качестве аргумента и возвращает y.

func createY(x: String) -> String {
    return x + "_test" // this computation could be much more complex
}

Затем просто вызовите его как обычно из init.

class MyClass {
  let x: String
  let y: String

  init(x: String) {
    self.x = x
    self.y = createY(x)
  }     
}

Ответ 2

Как ответил здесь, создайте функцию класса. Я добавил полный код.

class MyClass {
    var x: String
    var y: String

    class func createY(x: String) -> String {
         return x + "_test" // this computation could be much more complex
    }

    init(x: String) {
        self.x = x
        self.y = MyClass.createY(x)
    }     
}

Ответ 3

Я думаю, что быстрый способ сделать это - с помощью вычисляемых свойств (https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html)

ИЗМЕНИТЬ

Вместо вызова функции для изменения свойства в set/get вы можете использовать вычисленные свойства:

class MyClass {

    var x: String?
    var y: String? {
        get {
            return "\(x!)_test"
        }
    }

    init(x: String!){
       self.x = x
    }
}

let myClass = MyClass(x: "string") 
print(myClass.y!) #=> "string_test"

Ответ 4

В Swift 3 я использовал этот шаблон,

class MyClass {
  var x: String?
  private(set) lazy var y: String? = self.createY()

  init(x: String){ self.x = x }

  private func createY() -> String?
  {
    return "\(x ?? "nil") test"
  }
}

Секретный соус здесь - использование private(set) lazy. Таким образом, вы можете пометить ваше свойство a var. И lazy будет отсрочить инициализацию до тех пор, пока функция init не завершится. Использование private(set) позволяет только функциям внутри этого класса изменять это свойство, включая ключевое слово lazy, но не позволяет публичным интерфейсам его изменять. Конечно, если вы хотите, чтобы ваш интерфейс изменил ваше свойство, вы также можете пометить его internal (по умолчанию) или public. Но вам нужно оставить его отмеченным как lazy var

Ответ 5

Вы можете использовать в этом подходе

класс MyClass: NSObject {

        let x: String
        var y: String

        init(x: String) {

            self.x = x
            self.y = self.x + "_test"
            print(self.x)
            print(self.y)
        }
}

Ответ 6

class MyClass {
        let x: String
        lazy var y : String =  {
                return x + "_test"
            }()
        init(x: String) {
            self.x = x
        }
}