Swift错误:无法转换类型' B - >的值(A) - > ()'预期参数类型'(A) - >虚空'

时间:2016-03-08 16:21:51

标签: swift syntax

我有一个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()是等价的。

我甚至不理解双->的类型表达式。这是什么类型的?

任何人都可以解释这里有什么问题吗?而且,怎么做呢?

2 个答案:

答案 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)

@matt指出了正确的方向 - 非常感谢你。他的解决方案是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 } a2a3 不起作用。 a4a2生成原始“无法转换值”错误,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) { … } } 也无法使用,因为它尚未完全初始化。