代码之家  ›  专栏  ›  技术社区  ›  Liam

提取Swift类的常量属性的初始化代码

  •  2
  • Liam  · 技术社区  · 7 年前
    class Foo {
        let result: CGFloat
    
        init() {
            result = calculate()
        }
    
        private func calculate() -> CGFloat {
            // do many complex calculation with many codes
            return 0
        }
    }
    

    毫无疑问,这一错误发生了。

    在初始化所有存储属性之前,在方法调用“计算”中使用“self”`

    1. var 而不是 let . 例如 var result
    2. lazy . 例如 lazy result: CGFloat = { return 0 }
    3. calculate() class/static 或全局函数。例如 static func calculate() .

    但我想那不是我想要的。

    为什么? 允许

    允许 意思是不变的。通过计算 result 可能很复杂,但它确实是不变的。所以 这不是最好的做法。

    为什么? 计算()

    中的代码太多 init() 不是惯用的,令人讨厌的

    为什么不呢?

    静态函数中不能使用其他实例属性。


    使现代化

    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
        }
    }
    

    后果 同样的 foo3 foo3 = foo1 * foo2 但是 result = calculate()

    那是因为 后果 foo3 (只有一行)。如果我把这些代码都放进去 init()


    千方百计

    1. 变量 允许

    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
        }
    }
    

    它是有效的,但是 后果 这不是一成不变的。

    2.

    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
        }
    }
    

    它是有效的,但是 后果 也不是一成不变的。

    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()
        }
    }
    

    构建失败,

    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”,并将针对每次使用进行计算。

    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

    总结

    扩大

    “隐式展开选项”被多次提及。我不明白为什么直到看到 this answer

    2 回复  |  直到 7 年前
        1
  •  2
  •   jscs    7 年前

    result 变成一个

    • 计算属性

    第三种方法是,将计算移到自己的类型/自由函数,然后 提供

    Swift不允许您执行您试图执行的操作:规则是,在您对新实例的其他属性执行任何操作之前,必须设置所有存储的属性。它采取强硬的观点,认为任何不能证明是正确的东西都必须被禁止。

    例如,如果你改变了怎么办 calculate 阅读 ? 或者如果一个子类这样做了呢?您将遇到这样一种情况,即值不仅是未定义的,而且是不可定义的。