在 Swift class 的指定初始化器中调用实例方法
Calling an instance method in designated initializer of a Swift class
在Swift编程语言中,
是强制性的
“A designated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass initializer.” source of quote from another s/o
否则会显示类似下面的错误
Property 'self.baz' not initialized at super.init call
我想在 Swift 中实现以下 Objective-C 代码:
@interface FooBar : NSObject
@property (nonatomic, readonly) NSString *baz;
@end
@implementataion FooBar
@synthesize baz = _baz;
- (instancetype)initWithString:(NSString *)string {
self = [super init];
if (self) {
_baz = [self parseString:string];
}
return self;
}
- (NSString *)parseString:(NSString *)string {
// Perform something on the original string
return ...;
}
@end
以下实现会引发上述编译器错误:
class FooBar: NSObject {
let baz: NSString?
init(string: NSString?) {
super.init()
baz = parseString(string)
}
private func parseString(string: NSString?) -> NSString? {
// Perform something on the original string
return ...;
}
}
如果我执行以下操作,我会收到一条错误消息
Use of self in method call 'parseString' before super.init initialises self
class FooBar: NSObject {
let baz: NSString?
init(string: NSString?) {
baz = parseString(string)
super.init()
}
private func parseString(string: NSString?) -> NSString? {
// Perform something on the original string
return string;
}
}
所以我目前的解决方案是使用私有 class 方法:
class FooBar: NSObject {
let baz: NSString?
init(string: NSString?) {
baz = FooBar.parseString(string)
super.init()
}
private class func parseString(string: NSString?) -> NSString? {
// Perform something on the original string
return ...;
}
}
我的问题是是否有更好的方法来实现相同的目的,或者私有 class 方法是最好的方法吗?
正如您正确提到的那样,编译器会抱怨 "Use of self in method call 'parseString' before super.init initialises self"。这样做的原因是编译器必须确保您在完成初始化之前不会访问 self
上的任何内容。因为编译器不想(甚至不能)在初始化完成之前检查每个传出方法调用,所以它只是不允许在初始化完成之前使用任何 self。
幸运的是,您的方法 parseString
不想更改或访问任何 属性。因此你可以并且应该使它成为一个非实例函数。如果它与 FooBar
的实例无关,为什么它只能在 FooBar
的实例上可用?
您可以简单地将其设为 static
或 class
函数,就像您已经做的那样,这非常好。
但我会更进一步,将其完全移出 FooBar
。有几个选项:
- 创建一个 class
Helper
并将其定义为 class function
- 创建一个 class
Helper
并将其定义为 instance function
并在 class FooBar
中创建一个 Helper
实例或创建一个全局的,并在 init 中也传递那个。
在Swift编程语言中,
是强制性的“A designated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass initializer.” source of quote from another s/o
否则会显示类似下面的错误
Property 'self.baz' not initialized at super.init call
我想在 Swift 中实现以下 Objective-C 代码:
@interface FooBar : NSObject
@property (nonatomic, readonly) NSString *baz;
@end
@implementataion FooBar
@synthesize baz = _baz;
- (instancetype)initWithString:(NSString *)string {
self = [super init];
if (self) {
_baz = [self parseString:string];
}
return self;
}
- (NSString *)parseString:(NSString *)string {
// Perform something on the original string
return ...;
}
@end
以下实现会引发上述编译器错误:
class FooBar: NSObject {
let baz: NSString?
init(string: NSString?) {
super.init()
baz = parseString(string)
}
private func parseString(string: NSString?) -> NSString? {
// Perform something on the original string
return ...;
}
}
如果我执行以下操作,我会收到一条错误消息
Use of self in method call 'parseString' before super.init initialises self
class FooBar: NSObject {
let baz: NSString?
init(string: NSString?) {
baz = parseString(string)
super.init()
}
private func parseString(string: NSString?) -> NSString? {
// Perform something on the original string
return string;
}
}
所以我目前的解决方案是使用私有 class 方法:
class FooBar: NSObject {
let baz: NSString?
init(string: NSString?) {
baz = FooBar.parseString(string)
super.init()
}
private class func parseString(string: NSString?) -> NSString? {
// Perform something on the original string
return ...;
}
}
我的问题是是否有更好的方法来实现相同的目的,或者私有 class 方法是最好的方法吗?
正如您正确提到的那样,编译器会抱怨 "Use of self in method call 'parseString' before super.init initialises self"。这样做的原因是编译器必须确保您在完成初始化之前不会访问 self
上的任何内容。因为编译器不想(甚至不能)在初始化完成之前检查每个传出方法调用,所以它只是不允许在初始化完成之前使用任何 self。
幸运的是,您的方法 parseString
不想更改或访问任何 属性。因此你可以并且应该使它成为一个非实例函数。如果它与 FooBar
的实例无关,为什么它只能在 FooBar
的实例上可用?
您可以简单地将其设为 static
或 class
函数,就像您已经做的那样,这非常好。
但我会更进一步,将其完全移出 FooBar
。有几个选项:
- 创建一个 class
Helper
并将其定义为class function
- 创建一个 class
Helper
并将其定义为instance function
并在 classFooBar
中创建一个Helper
实例或创建一个全局的,并在 init 中也传递那个。