在Swift中初始化类常量

时间:2016-05-11 11:26:37

标签: swift

我试图做这样的事情(这是一个仅用于演示目的的人为例子):

class Test {
  let hello = "hello"
  let world = "world"
  let phrase: String {
    return self.hello + self.world
  }
}

但是你不能在Swift中使用let来计算属性。有没有办法在不必编写init()方法的情况下执行此操作?谢谢!

2 个答案:

答案 0 :(得分:5)

let无法处理只读计算属性的原因是因为它曾用于表明该属性的实际将会设置后永远不会改变 - 不是该属性是只读的。正如Apple docs所说(强调我的):

  

您必须声明计算属性 - 包括只读计算   properties - 作为var关键字的变量属性,因为它们的   值不固定。 let关键字仅用于常量   属性,表示一旦它们的值无法更改   被设置为实例初始化的一部分。

因此,您需要使用var来反映计算的属性值随时可能发生变化的事实,因为您在访问它时会动态创建它。虽然在您的代码中,但这不会发生 - 因为helloworld属性本身就是let个常量。但是,Swift无法推断出这一点,因此您仍然必须使用var

例如:

class Test {
    let hello = "hello"
    let world = "world"
    var phrase: String {
        return self.hello + self.world
    }
}

(这并没有改变财产的可读性 - 因为你还没有提供一个setter,它仍然是只读的)

但是,在您的情况下,您可能需要考虑使用lazy property,因为helloworld属性是常量。惰性属性在首次访问时会被创建,并在其生命的剩余时间内保持其值 - 这意味着每次访问它时都不必将两个常量连接在一起。

例如:

class Test {
    let hello = "hello"
    let world = "world"
    lazy var phrase: String = {
        return self.hello + self.world
    }()
}

let属性的另一个特征是在初始化之前应始终知道它们的值。由于之前可能不知道惰性属性的值,因此您还需要将其定义为var

如果您仍然坚持想要let属性,那么就我所知,您有两种选择。

第一个是最好的(虽然你已经说过你不想这样做) - 你可以在初始化者中分配你的phrase财产。只要您在super.init电话之前执行此操作,就不必处理可选项。例如:

class Test {
    let hello = "hello"
    let world = "world"
    let phrase: String

    init() {
        phrase = hello+world
    }
}

你根本无法内联,因为那个范围的self是指静态类,而不是类的实例。因此,您无法访问实例成员,必须使用init()或惰性/计算属性。

第二个选项非常糟糕 - 您可以在课程级别镜像helloworld属性,因此您可以在phrase声明中内联访问它们。例如:

class Test {
    static let hello = "hello"
    static let world = "world"

    // for some reason, Swift has trouble inferring the type
    // of the static mirrored versions of these properties
    let hello:String = Test.hello
    let world:String = Test.world

    let phrase = hello+world
}

如果您实际上不需要将helloworld属性作为实例属性,那么您可以将它们static - 这将解决您的问题。

答案 1 :(得分:2)

是的,使其作为计算属性工作,将let替换为var。 像,

class Test {
  let hello = "hello"
  let world = "world"
  var phrase: String {
     return self.hello + self.world
  }
}

这样你可以在没有init()

的情况下使用它