我如何分解一个大的init(由于大量的计算),以获得更好的可读性?

时间:2018-11-02 01:41:41

标签: swift initialization

我有一堂课,说100个属性(夸张)。 这些属性中的大多数必须根据用户的偏好进行计算。

这些属性在初始化后将不会更改,这就是为什么我想一开始就运行一次计算并将结果设置为let属性的原因

用户可以设置数十个首选项,并且根据设置的首选项组合,当我初始化对象时,此处的属性将更改。

let prop1:String
let prop2:String
...
let prop100:String

init(maybeRelevantArg:Int, maybeRelevantArg2:String) {
    var proposedProp1 = ""
    //20 lines of logic to compute proposedProp1, referencing preferences and maybeRelevantArgs
    self.prop1 = proposedProp1

    var proposedProp2 = ""
    //20 lines of logic to compute proposedProp2, referencing preferences and maybeRelevantArgs
    self.prop2 = proposedProp2
}

您明白了,在这一点上,我的init长了几百行,基本上是不可读的。

我想将这些逻辑块分成单独的方法,例如:

init(maybeRelevantArg:Int, maybeRelevantArg2:String) {
    self.computeAndSetProp1(relevantArg:maybeRelevantArg1)
    self.computeAndSetProp2(relevantArg:maybeRelevantArg2)
}

func computeAndSetProp1(relevantArg:String) {
    var proposedProp1 = ""
    //20 lines of logic to compute proposedProp1, referencing preferences and relevantArgs
    self.prop1 = proposedProp1
}

通过这种方式,init更具可读性,并且应该更容易调试和维护。

问题是,显然我的init方法没有显式初始化这些属性,编译器对此不满意,而我得到的类似于:

  

在所有存储属性初始化之前使用的“ self”

,而且在computeAndSetProp1()内,我将收到此错误:

  

无法分配给属性:“ prop1”是一个“ let”常量

有没有办法拆分这个大的init?

2 个答案:

答案 0 :(得分:1)

您可以将computeAndSetProp1()函数设为自由函数(即,不属于任何类),如下所示:

func computeAndSetProp1(relevantArg: String) -> String {
    var proposedProp1 = ""
    //20 lines of logic to compute proposedProp1, referencing preferences and relevantArgs
    return proposedProp1;
}

class someClass: NSObject {
    let prop1 : String
    let prop2 : String
    override init() {
        prop1 =  computeAndSetProp1(relevantArg: "x")
        //...etc.
    }
}

我还建议您查看是否可以泛化computeAndSetProp*函数以减少代码量。您随时可以将代码发布在Code Review上,以获取有关如何简化代码的更多想法。

答案 1 :(得分:0)

一种方法是将init参数存储在private let属性中,并将计算结果存储在已计算的var中。如果您希望计算逻辑只发生一次,也可以使用一个私有(设置)的惰性变量。

其他想法可能是将类分为具有相关属性的多个类/结构,然后使现有的类保留这些较小的类/结构。