gpt4 book ai didi

Swift 泛型 : "Cannot specialize non-generic type"

转载 作者:IT王子 更新时间:2023-10-29 05:52:22 25 4
gpt4 key购买 nike

我尝试使用通用协议(protocol)来实现面向对象的代码。假设我有两个协议(protocol)

protocol Executable: class {
func execute()
}

protocol Dockable: class {
associatedtype T
func dock(object: T)
}

我已经为可执行文件实现了一个装饰器:

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>) {}
}

但这不可能,因为协议(protocol)本身不是通用的,只有函数。编译器告诉我:

Cannot specialize non-generic type 'Dockable'

想法是这样使用它:

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 {}
}

看起来很奇怪,也许有人有更好的主意?现在使用类(class)时我得到:

Generic parameter 'DOCKABLE' could not be inferred

所以我的问题没有改变:

Swift 3 中的正确语法如何让编译器满意?

更新 2

似乎不可能在基于协议(protocol)的面向对象编程中使用快速通用(或更好:类型关联)协议(protocol)。

因此我们必须将它们包装到某种容器中并放松基于协议(protocol)的方法,或者我们必须为每种情况定义不同的协议(protocol)。

因为在没有协议(protocol)的情况下工作对我来说是不可能的,我必须在没有泛型的情况下编写不同的协议(protocol)。对 swift 感到羞耻😒

最佳答案

我不确定您的问题是否可以在不进行类型删除的情况下得到解决,因为您不能将协议(protocol)与关联类型用于变量类型或函数参数。

尝试使用类型删除的解决方案:

final class AnyDockable<U>: Dockable {
typealias T = U

let _dock: (U) -> Void
let _execute: () -> Void

init<Base: Dockable & Executable>(base: Base) where Base.T == U {
_dock = base.dock
_execute = base.execute
}

func dock(object: U) {
_dock(object)
}

func execute() {
_execute()
}
}

你的编译器会很高兴,我已经检查过了:

class Exe: Executable {
func execute() {
print("")
}
}
let executable: Executable = Exe()

let de = AnyDockable(base: DockableExecutable(executable))

final class MyViewController: UIViewController {

init(save: Executable, uiUpdateConnector: AnyDockable<Executable>) {
super.init(nibName: "", bundle: nil)
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

MyViewController(save: executable, uiUpdateConnector: de)

关于Swift 泛型 : "Cannot specialize non-generic type",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42887010/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com