【问题标题】:How to resolve collision between protocol and class fields types?如何解决协议和类字段类型之间的冲突?
【发布时间】:2019-04-11 12:51:28
【问题描述】:

我有一个协议和一个要扩展的类。协议需要某种类型的字段,并且该类有一个与此类型的隐式展开可选的名称和类型相同的字段。

这个类可以被这个协议扩展吗?如果是,那么如何?

如果我尝试编写扩展,Xcode 会给出不符合的错误。但是如果我将该字段添加到扩展中,它会给出重新声明的错误。

protocol Named {
   var name: String { get }
}

class Person {
   var name: String!
}


extension Person: Named { 
// Type 'Finances.Account' does not conform to protocol 'Named'
}

【问题讨论】:

  • 好吧,我会问一个显而易见的问题,类属性必须以这种方式声明的任何原因?
  • @JoakimDanielson,可能不打扰初始化。
  • @JoakimDanielson 它已由其他开发人员完成
  • 您可以为 Person 类创建一个包装类并让该类符合 Named 协议,但这感觉像是一个糟糕的解决方法。

标签: swift swift-protocols swift-extensions


【解决方案1】:

protocol 中声明的属性名称和类型必须与符合的类完全匹配。

因此,如果不更改协议或符合类型中的属性类型,您将无法解决错误。您还可以重命名其中一个属性并将匹配的属性添加到符合类型的新字段中。

所以要么做:

protocol Named {
   var name: String { get }
}

class Person {
    var name: String

    init(_ name:String) {
        self.name = name
    }
}


extension Person: Named {

}

或者

protocol Named {
   var name: String { get }
}

class Person {
   var _name: String!
}


extension Person: Named { 
    var name: String {
        return _name
    }
}

正如@user28434 指出的那样,有一个(n 丑陋的)解决方法。您可以创建一个与 Person 类的可选性匹配的包装协议,使该协议继承自原始协议,在新协议的扩展中声明非可选变量并使 Person 符合新协议原来的Named

protocol Named {
    var name: String { get }
}

class Person {
    var name: String!
}

protocol Namedd: Named {
    var name: String! { get }
}

extension Namedd {
    var name: String {
        return name!
    }
}

extension Person: Namedd {

}

【讨论】:

  • protocol 声明无效(也在问题中):需要访问说明符{get}/{get set}
  • 感谢您的回复。我理解你的两种方法,但如果限制改变它们怎么办?你有什么建议?
  • @user28434 你说得对,我将代码更新为可编译,而不仅仅是展示正确的方法
  • @ArtemiyShlesberg 你的意思是你无权访问这两种类型的源代码?在那种情况下,很遗憾你不能让给定的类型符合给定的协议。
  • @user28434 你甚至不需要任何转换,你可以简单地在新协议中返回强制解包name 变量。检查我的更新答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多