Make a protocol conform to another protocol

前端 未结 4 1360
臣服心动
臣服心动 2021-02-12 11:57

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

protoc         


        
相关标签:
4条回答
  • 2021-02-12 12:35

    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.

    0 讨论(0)
  • 2021-02-12 12:35

    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.

    0 讨论(0)
  • 2021-02-12 12:39

    I think if you check over at this SO answer, it solves the same problem.

    https://stackoverflow.com/a/37353146/1070718

    @paper1111 was close to what you're looking for, but I think you really want to do :

    extension InstrumentForProfessional where Self: Pen {}
    

    Since Pen already conforms to InstrumentForProfessional then you just need to extend InstrumentForProfessional when it is a Pen.

    Sometimes I forget how protocol inheritance works in Swift but thanks to SO for refreshing my memory.

    0 讨论(0)
  • 2021-02-12 12:43

    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.

    0 讨论(0)
提交回复
热议问题