web-dev-qa-db-ja.com

プロトコルを別のプロトコルに準拠させる

PenInstrumentForProfessionalの2つのプロトコルがあります。 PenInstrumentForProfessionalにしたい:

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
13
Richard Topchii

拡張機能のプロトコルへの準拠が必要な方法は次のとおりです。

_extension Pen where Self: InstrumentForProfessional {}
_

現在行っている方法では、コンパイラーは、プロトコルの適合性ではなく継承を行っていると見なします。

また、let pen = ApplePen() as InstrumentForProfessionalは意味がなく、コンパイルされません。

7
paper1111

プロトコルは互いに継承できます

プロトコルの継承

プロトコルは、1つまたは複数の他のプロトコルを継承し、継承する要件にさらに要件を追加できます。プロトコル継承の構文はクラス継承の構文に似ていますが、複数の継承プロトコルをコンマで区切ってリストするオプションがあります。

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

したがって、基本的にこれを行う必要があります:

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}
}

Penに準拠するものはすべてInstrumentForProfessionalにも準拠します。

4
user28434

2つの回答がすでに提供されています。@ user28434は、Penプロトコルを作成するときに適合性を追加できるという前提のもとでソリューションを提供し、@ paper1111は追加する機会を提供しています型がPenにも準拠する場合にのみ、InstrumentForProfessional拡張子に限定されます。注:@ paper1111の回答を利用するには、次のようにタイプにプロトコルを追加する必要もあります。

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

@ user28434からの回答よりも要件から逸脱しているようで、実際には別の質問(2つの異なるプロトコルを採用するタイプに機能を追加する方法)に回答しています。したがって、私はあなたが実際に探しているものがプロトコルではなくクラスの継承であるかどうか尋ねます:

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)
    }
}

両方のtitleプロパティの存在を介して得ているのは、クラス継承に共通のオーバーライド動作であるように思われるからです。それで問題は、とにかくclassまたはstructではなくenumを使用しているときに、クラスの継承をプロトコルに詰め込むことに取り組む必要があるのでしょうか。

クラスの継承を適用​​したくない場合、およびPenプロトコルの作成時に継承を追加したくない場合、およびクラスに複数のプロトコルを追加したくない場合は、あなたがきちんとするためにできるもう一つのことは、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
}

しかし、これをすべて書いた後、@ user28434のアプローチに従うことができれば、それに従ってください。

2
sketchyTech