J'ai deux protocoles: Pen et InstrumentForProfessional. Je voudrais faire de tout Pen un 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
Voici comment vous exigez la conformité aux protocoles dans les extensions.
extension Pen where Self: InstrumentForProfessional {}
La façon dont vous procédez actuellement fait penser au compilateur que vous faites l'héritage, pas la conformité au protocole.
Notez également que let pen = ApplePen() as InstrumentForProfessional
n'a pas de sens et ne compile pas.
Les protocoles peuvent hériter les uns des autres :
Héritage de protocole
Un protocole peut hériter d'un ou plusieurs autres protocoles et peut ajouter d'autres exigences en plus des exigences dont il hérite. La syntaxe de l'héritage de protocole est similaire à la syntaxe de l'héritage de classe, mais avec l'option de répertorier plusieurs protocoles hérités, séparés par des virgules:
protocol InheritingProtocol: SomeProtocol, AnotherProtocol { // protocol definition goes here }
Donc, vous devez essentiellement faire ceci:
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}
}
Maintenant, tout ce qui est conforme à Pen
est également conforme à InstrumentForProfessional
.
Deux réponses ont déjà été fournies: @ user28434 vous fournit une solution sous l'hypothèse que vous pouvez ajouter la conformité au moment où vous écrivez le protocole Pen
et @ paper1111 vous offre la possibilité de faire des ajouts à l'extension Pen
exclusive à l'endroit où le type est également conforme à InstrumentForProfessional
. Remarque: pour profiter de la réponse de @ paper1111, vous devez également ajouter le protocole à votre type comme ceci:
class ApplePen: Pen, InstrumentForProfessional {
var title: String = "CodePen"
var color: UIColor = .blue
}
Ce qui semble s'éloigner davantage de vos besoins que la réponse de @ user28434, et répond en fait à une question différente (comment ajouter des fonctionnalités à un type qui adopte deux protocoles différents). Par conséquent, je demanderais si ce que vous recherchez n'est pas un protocole mais un héritage de classe:
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)
}
}
Parce qu'il semble que ce que vous obtenez à travers l'existence de la propriété title
dans les deux est le comportement prioritaire commun à l'héritage de classe. La question devient donc pourquoi lutter pour compresser l'héritage de classe dans un protocole lorsque vous utilisez class
plutôt que struct
ou enum
de toute façon?
Si vous ne voulez pas appliquer l'héritage de classe et que vous ne voulez pas ajouter d'héritage au moment d'écrire le protocole Pen
, et si vous ne voulez pas non plus ajouter plusieurs protocoles à votre classe, alors une autre chose que vous pourriez faire pour la netteté est d'utiliser une 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
}
Mais après avoir écrit tout cela, si vous pouvez suivre l'approche de @ user28434, faites-le.