Make a protocol conform to another protocol

孤者浪人 提交于 2020-06-10 07:59:08

问题


I have two protocols: Pen and InstrumentForProfessional. I'd like to make any Pen to be an InstrumentForProfessional:

protocol Pen {
  var title: String {get}
  var color: UIColor {get}
}

protocol Watch {} // Also Instrument for professional
protocol Tiger {} // Not an instrument

protocol InstrumentForProfessional {
  var title: String {get}
}

class ApplePen: Pen {
  var title: String = "CodePen"
  var color: UIColor = .blue
}

extension Pen: InstrumentForProfessional {} // Unable to make ApplePen an Instument for Professional: Extension of protocol Pen cannot have an inheritance clause

let pen = ApplePen() as InstrumentForProfessional

回答1:


Protocols can inherit each other:

Protocol Inheritance

A protocol can inherit one or more other protocols and can add further requirements on top of the requirements it inherits. The syntax for protocol inheritance is similar to the syntax for class inheritance, but with the option to list multiple inherited protocols, separated by commas:

protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
    // protocol definition goes here
}

So, you basically need to do this:

protocol InstrumentForProfessional {
    var title: String {get}
}

protocol Pen: InstrumentForProfessional {
    var title: String {get} // You can even drop this requirement, because it's already required by `InstrumentForProfessional`
    var color: UIColor {get}
}

Now everything that conforms to Pen conforms to InstrumentForProfessional too.




回答2:


Here is how you require conformance to protocols in extensions.

extension Pen where Self: InstrumentForProfessional {}

The current way that you are doing makes the compiler think that you are doing inheritance, not protocol conformance.

Also note that let pen = ApplePen() as InstrumentForProfessional doesn't make sense and won't compile.




回答3:


Two answers have already been provided: @user28434 is providing you with a solution under the assumption that you can add the conformance at the time that you write the Pen protocol and @paper1111 is providing you with the opportunity to make additions to the Pen extension exclusive to where the type also conforms to InstrumentForProfessional. Note: to take advantage of @paper1111's answer you must also add the protocol to your type like so:

class ApplePen: Pen, InstrumentForProfessional {
  var title: String = "CodePen"
  var color: UIColor = .blue
}

Which seems to stray further from your requirements than the answer from @user28434, and in fact is answering a different question (which is how to add functionality to a type that adopts two different protocols). Therefore I would ask whether what you are actually looking for is not protocol but class inheritance:

class InstrumentForProfessional {
    var title: String
    init(title:String) {
        self.title = title
    }
}

class Pen: InstrumentForProfessional {
    var color: UIColor
    init(title:String, color:UIColor) {
        self.color = color
        super.init(title: title)
    }
}

Because it seems that what you are getting at through the existence of the title property in both is the overriding behaviour common to class inheritance. So the question becomes why wrestle to squeeze class inheritance into a protocol when you are using class rather than struct or enum anyway?

If you don't want to apply class inheritance and you don't want to add inheritance at the time of writing the Pen protocol, and if you also don't want to add multiple protocols to your class, then one other thing you could do for neatness is to use a typealias:

protocol InstrumentForProfessional {
    var title: String {get}
}

protocol PenExtra {
    var color: UIColor {get}
    var title: String {get}
}

typealias Pen = InstrumentForProfessional & PenExtra

class ApplePen: Pen {
    var title = "CodePen"
    var color = UIColor.blue
}

But having written all this, if you can follow @user28434's approach then do so.



来源:https://stackoverflow.com/questions/50966560/make-a-protocol-conform-to-another-protocol

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!