class Foo {
let result: CGFloat
init() {
result = calculate()
}
private func calculate() -> CGFloat {
// do many complex calculation with many codes
return 0
}
}
毫无疑问会发生错误。
在所有存储的属性初始化之前,在方法调用“计算”中使用的'self'
我知道几种解决此问题的方法。
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适合复杂的计算。
多次提到“隐式展开的可选内容”。我很困惑为什么直到看到this answer。
答案 0 :(得分:1)
您未提及的另外两种方式是将app.Use(async (HttpContext context, Func<Task> next) =>
{
context.Response.OnStarting(() =>
{
context.Response.Headers.Add("X-Added-Key", "X-Added-Value");
return Task.CompletedTask;
});
//await next();
try
{
await next();
}
catch (Exception ex)
{
context.Response.StatusCode = 500;
}
}).UseMvc();
变成其中一种
第三个是,将计算移至其自己的类型/自由函数,并提供至此类。可能是正确的解决方案。
Swift根本不允许您执行您要执行的操作:规则是必须设置所有存储的属性,然后才能对新实例的其他属性执行任何操作。坚决认为,任何无法证明正确的东西都必须被禁止。
例如,如果您将result
更改为从calculate
读取,该怎么办?或如果子类这样做了怎么办?您可能会遇到这样的情况,该值不仅是不确定的,而且是不确定的。