类型别名的无效重新声明

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&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;泛型已解决。请参阅下面的答案,如果我错了,请纠正 【参考方案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 嘿,马特,你能看看这个***.com/q/66154789/1404324,也许你能帮帮我。看来我的问题与此解决方案有关。

以上是关于类型别名的无效重新声明的主要内容,如果未能解决你的问题,请参考以下文章

核心数据类的无效重新声明

如何避免swift 3中的错误无效重新声明? [复制]

QML QtCreator 使用无效代码重新格式化组件类型的属性

因为该组节的条件字段不存在或无效所以无法打印

重新解释适当对齐的指向具有声明类型的对象的指针

在 Arduino 中重新声明为不同类型的符号