class Foo {
let result: CGFloat
init() {
result = calculate()
}
private func calculate() -> CGFloat {
// do many complex calculation with many codes
return 0
}
}
Нет сомнений, что ошибка возникает.
«self», используемое в вызове метода «Calculate» до инициализации всех сохраненных свойств`
Я знаю несколько способов решения этой проблемы.
var
вместо let
.например, var result
lazy
.например, lazy result: CGFloat = { return 0 }
- сделать
calculate()
равным class/static
или глобальной функции.например, static func calculate()
.
Но я думаю, что это не то, что я хочу.
Почему let
let
означает неизменность.Хотя расчет result
может быть сложным, но он действительно неизменен.Так что var
не лучшая практика.
Почему calculate()
Слишком много кодов в init()
не идиоматично и не раздражает
Почему бы не class/static
Другие свойства экземпляра нельзя использовать в статической функции.
Обновление
class Foo {
let foo1: CGFloat = 1.0
let foo2: CGFloat = 2.0
let foo3: CGFloat
let result: CGFloat
init() {
foo3 = foo1 * foo2
result = calculate()
}
private func calculate() -> CGFloat {
// do some calculation
let constants: CGFloat = 100
// (10 lines...)
return foo3 + constants
}
}
Для большей ясности я добавлю еще один фрагмент.На самом деле result
то же самое с foo3
.Так почему foo3 = foo1 * foo2
, а result = calculate()
?
Это потому, что вычисление result
(возможно, 10 строк кода) немного сложнее, чем вычисление foo3
(только одна строка).Если я введу все эти коды в init()
, это будет грязно.
Попробуйте все упомянутые способы
1.var
вместо let
class Foo {
let foo1: CGFloat = 1.0
let foo2: CGFloat = 2.0
let foo3: CGFloat
var result: CGFloat
init() {
foo3 = foo1 * foo2
result = calculate()
}
private func calculate() -> CGFloat {
// do some calculation
let constants: CGFloat = 100
// (10 lines...)
return foo3 + constants
}
}
Работает, но result
не является неизменным.
2.lazy
class Foo {
let foo1: CGFloat = 1.0
let foo2: CGFloat = 2.0
let foo3: CGFloat
lazy var result: CGFloat = {
calculate()
}()
init() {
foo3 = foo1 * foo2
}
private func calculate() -> CGFloat {
// do some calculation
let constants: CGFloat = 100
// (10 lines...)
return foo3 + constants
}
}
Работает, но result
также не является неизменным.
3.статическая функция
class Foo {
let foo1: CGFloat = 1.0
let foo2: CGFloat = 2.0
let foo3: CGFloat
let result: CGFloat
init() {
foo3 = foo1 * foo2
result = Foo.calculate()
}
static private func calculate() -> CGFloat {
// do some calculation
let constants: CGFloat = 100
// (10 lines...)
return foo3 + constants
}
}
Сборка не удалась,
Элемент экземпляра 'foo3' нельзя использовать для типа 'Foo'
4.закрытие
class Foo {
let foo1: CGFloat = 1.0
let foo2: CGFloat = 2.0
let foo3: CGFloat
let result: CGFloat
private let calculate = { () -> CGFloat in
// do some calculation
let constants: CGFloat = 100
// (10 lines...)
return foo3 + constants
}
init() {
foo3 = foo1 * foo2
result = calculate()
}
}
Сборка не удалась,
Элемент экземпляра 'foo3' нельзя использовать для типа 'Foo'
5.вычислительное свойство
class Foo {
let foo1: CGFloat = 1.0
let foo2: CGFloat = 2.0
let foo3: CGFloat
var result: CGFloat {
// do some calculation
let constants: CGFloat = 100
// (10 lines...)
return foo3 + constants
}
init() {
foo3 = foo1 * foo2
}
}
Работает, но результатом является 'var' и будет рассчитываться для каждого использования.
6.класс инструмента
class Foo {
let foo1: CGFloat = 1.0
let foo2: CGFloat = 2.0
let foo3: CGFloat
let result: CGFloat
init() {
foo3 = foo1 * foo2
result = Tool.calculate(foo3: foo3)
}
}
class Tool {
static func calculate(foo3: CGFloat) -> CGFloat {
// do some calculation
let constants: CGFloat = 100
// (10 lines...)
return foo3 + constants
}
}
Работает, но мы вводим Tool
класс.
Резюме
1, 2, 6 подходит.6 подходит для сложных вычислений.
Расширение
"Неявно развернутые необязательные параметры" упоминается несколько раз.Я запутался, почему пока не вижу этот ответ .