我有一个Swift程序,它产生一个我无法理解的编译器错误。它归结为以下代码片段。
类A
是一个辅助类,在初始化时提供了一个稍后要调用的处理函数。此函数有一个A
对象作为参数。
类B
初始化类型为A
的对象,并且具有应该用作处理程序的函数f
。或者,可以提供匿名代码块(闭包)。
class A {
init(_: (A) -> Void) {}
}
class B {
let a = A(f)
func f(a: A) {}
}
这会产生以下编译器消息:
error: cannot convert value of type 'B -> (A) -> ()' to expected argument type '(A) -> Void'
let a = A(f)
^
我想, Void
和()
是等价的。
我甚至不理解双->
的类型表达式。这是什么类型的?
任何人都可以解释这里有什么问题吗?而且,怎么做呢?
答案 0 :(得分:4)
初始化实例属性(如f
)时,您无法引用实例方法(如a
),因为实例正是我们在创建过程中的实例。一种解决方案是声明您的实例属性lazy
,如下所示:
class A {
init(_: (A) -> Void) {}
}
class B {
func f(a: A) {}
lazy var a : A = A(self.f)
}
这是合法的,因为lazy
保证a
的初始化程序不会被评估,直到以后,当实例 时已创建。请注意,在此上下文中绝对需要self
(一般情况下,我建议您始终在任何可以使用的地方使用它。)
另一个解决方案是将a
声明为A!
(以便它具有初始值,即nil
)并将其初始化为#34;对于真实的"后来。例如:
class A {
init(_: (A) -> Void) {}
}
class B {
func f(a: A) {}
var a : A!
init() {
self.a = A(self.f)
}
}
答案 1 :(得分:0)
padding:1px
变体:
a1
有趣的是,所有其他变体class B {
func f(a: A) {}
lazy var a1 : A = A(self.f) // ok
lazy var a2 : A = A(f) // error
lazy var a3 = A(self.f) // error
lazy var a4 = A(f) // error
}
,a2
,a3
不起作用。 a4
和a2
生成原始“无法转换值”错误,a4
说“使用未解析的标识符'self'”
a3
解决方案的缺点是lazy
现在是a
而不是常量。我通过在初始化期间分配常量值找到了另一种方法:
var
有趣的是,此仅适用于闭包。代码
class B {
let a: A
init() {
a = A() { (A) -> Void in … } // ok
}
}
在初始化所有存储的属性之前,给出编译器错误“在方法调用'f'中使用'self'。。
尽管如此,即使在闭包变体中,class B {
let a: A
init() {
a = A(f) // error
}
func f(a: A) { … }
}
也无法使用,因为它尚未完全初始化。