【问题标题】:Implementing generic protocols Error by compiler编译器实现泛型协议错误
【发布时间】:2018-03-27 22:12:54
【问题描述】:

我正在尝试在我的应用程序中使用通用协议。我尝试使用的代码是这样的。

protocol BaseProtocol {
  associatedtype PresenterType
  var presenter: PresenterType? { get set }
}

protocol PresenterProtocol {
  associatedtype View
  var view: View? { get set }
}

protocol ChildPresenter: PresenterProtocol where View == ChildProtocol {

}

protocol ChildProtocol: BaseProtocol where PresenterType == ChildPresenter {

}


class A: ChildProtocol {
  var presenter: ChildPresenter?
}

编译器在符合 ChildProtocol 时抛出错误

错误:协议“ChildPresenter”只能用作泛型 约束,因为它具有 Self 或关联的类型要求 var 主持人:ChildPresenter?

当我已经清除了 associateType 时,我不明白为什么编译器会抛出此错误。

【问题讨论】:

  • 如果您不明白为什么会出错,我在回答中添加了解释。

标签: swift generics protocols


【解决方案1】:

正如错误所说,ChildPresenter 可以用作泛型,因此您必须将其放在类的声明中,例如。 class A<T: ChildPresenter> : ChildProtocol

protocol BaseProtocol {
    associatedtype PresenterType
    var presenter: PresenterType? { get set }
}

protocol PresenterProtocol {
    associatedtype View
    var view: View? { get set }
}

protocol ChildPresenter: PresenterProtocol where View == ChildProtocol {

}

protocol ChildProtocol: BaseProtocol {

}


class A<T: ChildPresenter> : ChildProtocol {
    var presenter: T?
    func foo(bar: T) {

    }
}

你也可以用ChildPresenter代替T,像这样

class A<ChildPresenter> : ChildProtocol {
    var presenter: ChildPresenter?
}

乍一看,这似乎对你的类A有一点限制,因为你必须在初始化之前指定ChilPresenter的类型,以后不能修改,但是这是必要的,因为ChildPresenter有一个关联类型。

您可以看到,如果没有泛型,您可能会遇到麻烦,想象一下 BaseProtocol 多了一个属性

protocol BaseProtocol {
    associatedtype PresenterType
    var presenter: PresenterType? { get set }
    var presented: PresenterType? { get set }
}

presenterpresented 必须是同一个类型,因为你在这里说过

class A 也将拥有一个属性:

class A<ChildPresenter> : ChildProtocol {
    var presenter: ChildPresenter?
    var presented: ChildPresenter?
}

这样,您可以保证presenterpresented 始终具有相同的类型,因为您在创建A 的对象时选择了该类型,例如。 let a = A&lt;Foo&gt;()

没有泛型,它看起来像这样

class A: ChildProtocol {
    var presenter: ChildPresenter?
    var presented: ChildPresenter?
}

这样,presenter 可以是 Foo 类型,presented 可以是 Bar 类型。所以你最终会遇到一个悖论。这就是为什么您需要在A 的声明中设置泛型类型。

【讨论】:

  • 在做'class A : ChildProtocol { var presenter: ChildPresenter? }'
  • 编译器抛出错误:'ChildProtocol' 要求类型 'ChildPresenter' 和 'ChildPresenter' 等价类 A: ChildProtocol { 注意:要求指定为 'Self.PresenterType' == 'ChildPresenter ' [with Self = A] 类 A: ChildProtocol {
  • 您必须删除ChildProtocol 声明中的where 子句
猜你喜欢
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
  • 2021-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多