Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift仿制药公司:;无法专门化非泛型类型“;_Swift_Oop_Generics - Fatal编程技术网

Swift仿制药公司:;无法专门化非泛型类型“;

Swift仿制药公司:;无法专门化非泛型类型“;,swift,oop,generics,Swift,Oop,Generics,我试图通过使用通用协议来实现面向对象的代码。 假设我有两个协议 protocol Executable: class { func execute() } protocol Dockable: class { associatedtype T func dock(object: T) } 我已经为可执行文件实现了一个decorator: final class DockableExecutable: Executable, Dockable { typeali

我试图通过使用通用协议来实现面向对象的代码。 假设我有两个协议

protocol Executable: class {
    func execute()
}

protocol Dockable: class {
    associatedtype T
    func dock(object: T)
}
我已经为可执行文件实现了一个decorator:

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 {}
}
最终类MyViewController:UIViewController{
init(save:Executable,uiUpdateConnector:DOCKABLE),其中DOCKABLE.T:Executable{}
}
看起来很奇怪,也许有人有更好的主意?现在使用该类时,我得到:

无法推断泛型参数“可停靠”

所以我的问题没有改变:

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

更新2

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

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


因为我没有选择在没有协议的情况下工作,所以我必须在没有泛型的情况下编写不同的协议。斯威夫特的耻辱我不确定你的问题是否能在没有类型擦除的情况下得到解决,因为你不能对变量类型或函数参数使用具有关联类型的协议

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

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()
    }
}
final类AnyDockable:Dockable{
类型别名T=U
让_停靠:(U)->Void
让_执行:()->Void
init(base:base),其中base.T==U{
_dock=base.dock
_execute=base.execute
}
func dock(对象:U){
_停靠(对象)
}
func 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)
class-Exe:可执行文件{
func execute(){
打印(“”)
}
}
let executable:executable=Exe()
设de=AnyDockable(基:DockableExecutable(可执行))
最终类MyViewController:UIViewController{
init(保存:可执行,uiUpdateConnector:AnyDockable){
super.init(nibName:,bundle:nil)
}
必需的初始化?(编码器aDecoder:NSCoder){
fatalError(“初始化(编码者:)尚未实现”)
}
}
MyViewController(保存:可执行文件,uiUpdateConnector:de)

如果我没记错的话,您是在寻找协议组成(多协议一致性),不是吗?之后你可以使用不同的装饰师

也许你正在寻找这个: Swift 3
协议


看看这篇文章,看看它是否能给你一个启示:谢谢你的链接,@leanne。但我认为情况不同。我已经设法从一个通用协议中派生出来(参见上面的可停靠可执行实现)。现在我尝试使用协议。您的链接描述了我在更新中编写的解决方案。因此,我认为这是解决方案的一部分。(投票赞成)另一个可能给你启发的链接:-你的更新看起来很相似;但是,OP已经将协议添加到视图控制器的类签名中,或者在您的示例中:
final类MyViewController:UIViewController,可停靠{
您遇到的问题是–因此您不能将
可执行文件
用作符合
可执行文件
的类型。您可以将
where
子句更改为
where DOCKABLE.T==可执行文件
,但这样就只能接受
可执行文件
类型,其中
T
可执行文件
>(不是符合
可执行文件的
T
)。我必须做一点实验,直到我能告诉你它是否对我有帮助。在你当前的实现中,参数uiUpdateConnector不再是协议,而是具体的类AnyDockable。这违反了我基于协议的面向对象方法。AnyDockable也特别链接到可执行文件。因此,如果我写一个DockableleStringValue/DockableHatEver/。我还必须为所有这些类实现一个类似于AnyDockable的类。这打破了泛型的概念。泛型可停靠接口没有任何意义。你不认为吗?我认为你是对的。不可能:-/-“投票赞成”对于答案的这一部分,我将等待一点,然后接受它作为答案。也许一些天才告诉我们我们错了;-)是的,你是对的。AnyDockableExecutable应该命名为AnyDockableExecutable。我不认为类型擦除AnyDockableExecutable违反了基于协议的设计,因为它就像一个协议:所有的实现细节都是仍然隐藏。事实上,Swift标准库使用此模式
uiUpdateConnector
是否必须符合可执行协议?如果不符合,则可以从任何可固定文件中删除可执行部分,其行为类似于泛型类型(字符串,无论什么)。
final class MyViewController: UIViewController {
    init(save: Executable, uiUpdateConnector: protocol<Dockable, Executable>) {}
}