类型别名的无效重新声明
Posted
技术标签:
【中文标题】类型别名的无效重新声明【英文标题】:Invalid redeclaration of typealias 【发布时间】:2018-11-09 21:53:43 【问题描述】:我有一个泛型协议TwoWayBindDelegate
,它使用泛型关联类型来确定函数twoWayBind()
的参数
protocol TwoWayBindDelegate: class
associatedtype BindType
func twoWayBind(to observable: Observable<BindType>?, observableChanged: ((BindType) -> ())?)
然后我创建了一个类Reactive<Base: UIView, Type>
(符合TwoWayBindDelegate
),您必须在其中使用通用Base
对其进行初始化。例如:let reactiveSlider = Reacive<UISlider>(slider)
。
我的问题是,当我扩展 Reactive 并符合 TwoWayBindDelegate
时,我收到错误 Invalid redeclaration of 'BindType'
,因为我在两个扩展中都声明了 BindType
和 twoWayBind()
。有没有办法让两个扩展都为TwoWayBindDelegate
提供不同的实现
class Reactive<Base: UIView>: TwoWayBindDelegate
public var base: Base
init(base: Base)
self.base = base
extension Reactive where Base == UISlider
typealias BindType = Float
func twoWayBind(to observable: Observable<Float>?, observableChanged: ((Float) -> ())?)
// implement two way bind for UISlider
extension Reactive where Base == UITextField
typealias BindType = String
func twoWayBind(to observable: Observable<String>?, observableChanged: ((String) -> ())?)
// implement two way bind for UITextField
我做了一些研究,发现这可能是一个错误https://bugs.swift.org/browse/SR-5392。有没有办法解决
【问题讨论】:
我正在使用BindType
,因此twoWayBind()
中的参数可以是BindType
类型。因此,如果BindType
是字符串,则参数将是 ObservableObservable<String>
,我们知道 BindType 必须是String;泛型已解决。请参阅下面的答案,如果我错了,请纠正我。
【参考方案1】:
我不太明白typealias
的用途。仅函数声明就足以告诉编译器BindType
必须是什么。
我在您的代码中发现的问题(当然,除了缺少的 Observable 声明)是 Reactive 类本身不符合 TwoWayBindDelegate。为了解决这个问题,我加入了twoWayBind
的任意实现。当我这样做时,当我删除不必要的 typealias
声明时,您的代码为我编译:
struct Observable<T>
protocol TwoWayBindDelegate: class
associatedtype BindType
func twoWayBind(to observable: Observable<BindType>?, observableChanged: ((BindType) -> ())?)
class Reactive<Base: UIView>: TwoWayBindDelegate
public var base: Base
init(base: Base)
self.base = base
func twoWayBind(to observable: Observable<Int>?, observableChanged: ((Int) -> ())?)
extension Reactive where Base == UISlider
func twoWayBind(to observable: Observable<Float>?, observableChanged: ((Float) -> ())?)
extension Reactive where Base == UITextField
func twoWayBind(to observable: Observable<String>?, observableChanged: ((String) -> ())?)
【讨论】:
谢谢,效果很好!需要明确的是,基类中声明的twoWayBind()
仅在Base
不是UISlider
或UITextField
时运行,对吗?
试试看!
顺便说一句,我应该补充一点,您遇到的问题在很大程度上是由于(在我看来)非常不幸地二次使用保留字 typealias
作为一种显式解析协议泛型associatedtype
。我对此提交了一份错误报告 (rdar://24792823),但没有取得进展。
@matt 嘿,马特,你能看看这个***.com/q/66154789/1404324,也许你能帮帮我。看来我的问题与此解决方案有关。以上是关于类型别名的无效重新声明的主要内容,如果未能解决你的问题,请参考以下文章