I am new to Swift and would like to initialize an object's member variable using an instance method like this:
class MyClass {
var x: String
var y: String
func createY() -> String {
self.y = self.x + "_test" // this computation could be much more complex
}
init(x: String) {
self.x = x
self.y = self.createY()
}
}
Basically, instead of inlining all the initialization code in init
method, I want to extract the initialization code of y
to a dedicated method createY
and call this instance method createY
in init
. However, Swift compiler (Swift 1.2 compiler in Xcode 6.3 beta) complains:
use of 'self' in method call 'xxx' before super.init initialize self
Here 'xxx' is the name of the instance method (createY).
I can understand what Swift compiler is complaining and the potential problem it wants to address. However, I have no idea how to fix it. What should be the correct way in Swift to call other instance method of initialization code in init
?
Currently, I use the following trick as work around but I don't think this is the idiomatic solution to this problem (and this workaround requires y
to be declared using var
instead of let
which makes me feel uneasy too):
init(x: String) {
self.x = x
super.init()
self.y = createY()
}
Any comment is appreciated. Thanks.
Convert createY()
to a global or class function that accepts x
as an argument and returns a y
.
func createY(x: String) -> String {
return x + "_test" // this computation could be much more complex
}
Then just call it normally from your init
.
class MyClass {
let x: String
let y: String
init(x: String) {
self.x = x
self.y = createY(x)
}
}
In Swift 3, I've been using this pattern,
class MyClass {
var x: String?
private(set) lazy var y: String? = self.createY()
init(x: String){ self.x = x }
private func createY() -> String?
{
return "\(x ?? "nil") test"
}
}
The secret sauce here is the use of private(set) lazy
. This way, you can label your property a var
. And lazy
will delay initialization until after your init
function has completed. Using private(set)
only allows the functions inside this class to modify that property, including the lazy
keyword, but not let public interfaces change it. Of course, if you want your interface to change your property, then you can also mark it internal
(the default) or public
. But you need to leave it marked a lazy var
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With