class Test { let hello = "hello" let world = "world" let phrase: String { return self.hello + self.world } }
但你不能在Swift中使用let来计算属性.有没有办法在不必编写init()方法的情况下执行此操作?谢谢!
let之所以对read-only计算属性不起作用,是因为它用于声明属性的实际值在设置后永远不会改变 – 而不是该属性是只读的.正如 Apple docs所说(强调我的):You must declare computed properties — including read-only computed
properties — as variable properties with the var keyword, because their
value is not fixed. The let keyword is only used for constant
properties, to indicate that their values cannot be changed once they
are set as part of instance initialization.
因此,您需要使用var来反映计算属性值随时可能发生变化的事实,因为您在访问它时会动态创建它.虽然在你的代码中,这不可能发生 – 因为你的hello和world属性是自己的常量.但是,Swift无法推断出这一点,所以你仍然需要使用var.
例如:
class Test { let hello = "hello" let world = "world" var phrase: String { return self.hello + self.world } }
(这不会改变属性的可读性 – 因为你没有为它提供setter,它仍然是只读的)
但是在您的情况下,您可能需要考虑使用lazy property,因为您的hello和world属性是常量.惰性属性在首次访问时创建,并在其生命周期的剩余时间内保持其值 – 这意味着每次访问它时都不必继续将两个常量连接在一起.
例如:
class Test { let hello = "hello" let world = "world" lazy var phrase: String = { return self.hello + self.world }() }
let属性的另一个特征是它们的值应该在初始化之前始终是已知的.因为在此之前可能不知道惰性属性的值,所以还需要将其定义为var.
如果你仍然坚持想要一个let属性,那么据我所知,你有两个选择.
第一个是最好的(尽管你已经说过你不想这样做) – 你可以在初始化器中分配你的短语属性.只要你在super.init调用之前执行此操作,就不必处理选项.例如:
class Test { let hello = "hello" let world = "world" let phrase: String init() { phrase = hello+world } }
你根本无法内联,因为该范围的self指的是静态类,而不是类的实例.因此,您无法访问实例成员,并且必须使用init()或惰性/计算属性.
第二个选项很糟糕 – 您可以在类级别镜像您的hello和world属性,因此您可以在短语声明中内联访问它们.例如:
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 }
如果您实际上不需要将hello或world属性作为实例属性,那么您可以将它们设置为静态 – 这将解决您的问题.