Вызов метода экземпляра во время инициализации в 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
}
}