【发布时间】:2017-03-19 13:15:21
【问题描述】:
我尝试使用通用协议来实现面向对象的代码。 假设我有两个协议
protocol Executable: class {
func execute()
}
protocol Dockable: class {
associatedtype T
func dock(object: T)
}
我已经为 Executable 实现了一个装饰器:
final class DockableExecutable: Executable, Dockable {
typealias T = Executable
private let decorated: Executable
private var docked: Executable?
init(_ decorated: Executable) {
self.decorated = decorated
}
// from Executable
func execute() {
decorated.execute()
docked?.execute()
}
// from Dockable
func dock(object: Executable) {
docked = object
}
}
现在我不想在这样的课程中使用它:
final class MyViewController: UIViewController {
init(save: Executable, uiUpdateConnector: Dockable<Executable>) {}
}
但这是不可能的,因为协议本身不是通用的,只有函数。编译器告诉我:
无法专门化非泛型类型“可停靠”
我们的想法是这样使用它:
let dockableExecutable = DockableExecutable(
SQLUpdateExecutable(/** dependencies **/)
)
let controller = MyViewController(save: dockableExecutable, uiUpdateConnector: dockableExecutable)
Swift 3 中的正确语法如何让编译器满意?
更新 1
我使用以下代码取得了一些进展:
final class MyViewController: UIViewController {
init<DOCKABLE: Dockable>(save: Executable, uiUpdateConnector: DOCKABLE) where DOCKABLE.T: Executable {}
}
看起来很奇怪,也许有人有更好的主意?现在使用该课程时,我得到:
无法推断通用参数“DOCKABLE”
所以我的问题没有改变:
Swift 3 中的正确语法如何让编译器满意?
更新 2
似乎不可能在基于协议的面向对象编程中使用 swift 通用(或更好:类型关联)协议。
所以我们必须将它们包装到某种容器中并松散基于协议的方法,或者我们必须为每种情况定义不同的协议。
因为我无法选择不使用协议,所以我必须编写不使用泛型的不同协议。羞愧于斯威夫特????
【问题讨论】:
-
看看这个,看看它是否给你一个洞察力:How to create generic protocols in Swift? - Stack Overflow
-
感谢您的链接,@leanne。但我认为这是一个不同的情况。我已经设法从通用协议派生(参见上面的 DockableExecutable 实现)。现在我尝试使用协议。
-
您的链接描述了我在更新中编写的解决方案。因此,我认为这是解决方案的一部分。 (投票)
-
另一个可以让您深入了解的链接:ios - Generics in Swift - "Generic parameter 'T' could not be inferred - Stack Overflow - 您的更新看起来很相似;但是,那里的 OP 已将协议添加到视图控制器的类签名中,或者在您的情况下:
final class MyViewController: UIViewController, Dockable { -
您遇到的问题是protocols don't conform to themselves - 因此您不能将
Executable用作符合Executable的类型。您可以将where子句更改为where DOCKABLE.T == Executable,但那将只接受TisExecutable的Dockable类型(不是符合T的Executable)。