初始化变量时如何防止重复代码?

时间:2016-06-19 03:53:34

标签: swift

一个类有一些变量要在init()中初始化,同时,该类提供了一个函数,可以将这些变量恢复为restoreInitValues()中的初始值。有没有办法在没有在init()restoreInitValues()内设置两次这些值(重复代码)的情况下实现这一目标?

class Foo {
    var varA: Int
    var varB: Int
    var varC: Int

    init() {
        //restoreInitValues() // error: call method before all stored proproties are initalized

        //or I have to have duplicate code here as restoreInitValues below
        varA = 10
        varB = 20
        varC = 30
    }

    func restoreInitValues() {
        varA = 10
        varB = 20
        varC = 30
    } 
}

3 个答案:

答案 0 :(得分:1)

我个人会将3个默认值分配给3个类范围常量,然后使用这些值进行初始化和恢复。如果需要,还可以在init中消除赋值语句,并在声明var时分配值。此外,如果您需要在类中添加任何其他函数,则可以将类中的默认值定义为常量。

class Foo {
let defaultA = 10
let defaultB = 20
let defaultC = 20
var varA: Int
var varB: Int
var varC: Int

    init() {
    varA = defaultA
    varB = defaultB
    varC = defaultC
    }

    func restoreInitValues() {
    varA = defaultA
    varB = defaultB
    varC = defaultC
    } 
}

您还可以定义一个结构,使用它来赋值,然后使用重置函数进行初始化。

struct values{

static let defaultA = 10
static let defaultB = 20
static let defaultC = 30

}


class test {

var a: Int = 0
var b: Int = 0
var c: Int = 0

    init(){
         resetValues()
    }

    func resetValues(){

        (a, b, c) = (values.defaultA, values.defaultB, values.defaultC)

    }

}

答案 1 :(得分:1)

更新:Code's answer below关于Implicitly Unwrapped Optionals就是答案。我不确定为什么我以前在文档中找不到它。我要留下我的答案给后人,但你应该接受Code's answer

刚接触swift,我试了一下,找到了这两个解决方案,但我不确定它们是不是最好的解决方案。

问题似乎是swift努力确保在执行初始化之后没有类实例将具有未初始化的属性(除非它们被标记为可选)。它不会让您调用非静态方法,因为您可能在设置所有属性之前使用该实例。此外,它不相信你会调用另一个为你初始化所有属性的方法,大概是因为这很难验证。

对于类,使用私有静态方法返回默认值:

class Foo {
  //...
  init() {
    (varA, varB, varC) = Foo.defaultValues()
  }

  func restoreInitValues() {
    (varA, varB, varC) = Foo.defaultValues()
  }

  static private func defaultValues() -> ( Int, Int, Int ) {
    return (10, 20, 30)
  }
}

如果您不需要类,则可以按值复制结构:

struct Foo {
  //...
  mutating func restoreInitValues() {
    self = Foo()
  }
}

或者您可以放弃restoreInitValues()并执行此操作:

var f = Foo()
f.varA = 10000
// instead of resetting the internal state of `f`, just replace it with
// a new `Foo` instance
f = Foo()

或者您可以使用修改Foo实例的静态私有方法,但要绕过编译器,您必须使属性成为可选。这个解决方案有一个明确的Ick因素:

class Foo {
  var varA: Int?
  var varB: Int?
  var varC: Int?

  init() {
    Foo.resetValues(in: self)
  }

  func restoreInitValues() {
    Foo.resetValues(in: self)
  }

  static private func resetValues(in foo: Foo) {
    foo.varA = 10
    foo.varB = 20
    foo.varC = 30
  }
}

这使我们回到问题的核心:swift要求所有属性都是可选的或初始化的。另一种解决方案是简单地给出所有属性值(无意义或无意义)。缺点是属性定义可能会误导第一次阅读代码的人。

class Foo {
  var varA = -1
  var varB = -1
  var varC = -1

  init() {
    restoreInitValues()
  }

  func restoreInitValues() {
    varA = 10
    varB = 20
    varC = 30
  }
}

最后,请查看此类似问题的答案:How to implement two inits with same content without code duplication

答案 2 :(得分:1)

使用隐式解包的选项。

class Foo {
    var varA: Int!
    var varB: Int!
    var varC: Int!

    init() {
        restoreInitValues()
    }

    func restoreInitValues() {
        varA = 10
        varB = 20
        varC = 30
    } 
}