【问题标题】: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&lt;Base: UIView, Type&gt;(符合TwoWayBindDelegate),您必须在其中使用通用Base 对其进行初始化。例如:let reactiveSlider = Reacive&lt;UISlider&gt;(slider)

我的问题是,当我扩展 Reactive 并符合 TwoWayBindDelegate 时,我收到错误 Invalid redeclaration of 'BindType',因为我在两个扩展中都声明了 BindTypetwoWayBind()。有没有办法让两个扩展都为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 是字符串,则参数将是 Observable。如果我摆脱关联的类型,协议函数的参数将是什么类型?我对泛型没有太多经验,所以如果我错了,我会纠正我。
  • 在我看来,你倒退了。如果你在声明中说Observable&lt;String&gt;,我们知道 BindType 必须是String;泛型已解决。请参阅下面的答案,如果我错了,请纠正

标签: swift generics


【解决方案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 不是UISliderUITextField 时运行,对吗?
  • 试试看!
  • 顺便说一句,我应该补充一点,您遇到的问题在很大程度上是由于(在我看来)非常不幸地二次使用保留字 typealias 作为一种显式解析协议泛型associatedtype。我对此提交了一份错误报告 (rdar://24792823),但没有取得进展。
  • @matt 嘿,马特,你能看看这个stackoverflow.com/q/66154789/1404324,也许你能帮帮我。看来我的问题与此解决方案有关。
猜你喜欢
  • 1970-01-01
  • 2017-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多