2016-03-22 11 views
7

アップルが提供するビデオチュートリアルを見てみると、プロトコル指向のプログラミングラングとリンゴは、プログラマがクラスよりもプロトコルを使用するよう促しているようです。 私の個人的見解では、プロトコルに明らかな利点はないと思う。クラスはプロトコルに準拠することができますが、スーパークラスから継承することもできます。プロトコルに拡張を追加できますが、クラスに拡張を追加することもできます。プロトコルに準拠したクラスで関数を実装できますが、サブクラスで関数funcをオーバーライドすることもできます。 私はまだ、クラスではなくプロトコルを使用する必要があるという理由で、混乱しています。クラスの代わりにプロトコルを使用する必要があるときなぜプロトコルは迅速にクラスより優れていますか?

+1

私の例です: 'Vehicle'と' BuildingMaterial'から継承する 'Wood'を継承した' Car'を 'Car'と' Wood'に 'burn'メソッドを追加したい場合は、プロトコルが最も適合するでしょう。 – tktsubota

+0

WWDC 2015の[プロトコル指向プログラミング](https://developer.apple.com/videos/play/wwdc2015/408/)では、どのビデオを参照しているのかわかりませんが、詳細は、プロトコルのメリット。 – Rob

答えて

6

ダウンロードの例を取っ​​てください。

あなたはFileDownloadModel基本クラスを持っており、3つのサブクラスAudioFileDownloadModel、VideoFileDownloadModel、ImageDownloadModelを持っています。

あなたはFileDownloadModelとして入力を受け取り、ファイルをダウンロードするには、モデルのそのurlToDownloadプロパティを使用していますDownloadManagerを持っています。

後にラインの下のあなたがそこに来て1つの以上のモデルであるが、そのようなUserDownloadModelサブクラスからユーザー、と言われています。

ここで、ダウンロード方法を組み込むために多くのコードを変更する必要があるこのようなシナリオを処理するのが難しくなりました。

プロトコル指向プログラミングは、ここであなたを助ける方法:

  1. DownloadingFileProtocolという名前のプロトコルを作成し、ファイルをダウンロードするために必要な メソッドを追加します。例えば。 urlToDownload、 pathToSave、拡張等
  2. FileDownloadModelで同じプロトコルを実装し UserDownloadModel。 のコードを多く変更する必要がないという利点を参照してください。UserDownloadModel メソッドは、ダウンロードファイルプロトコルから実装するだけです。
  3. もう一度新しいエンティティがラインを下ってきたら、 のコードを変更するだけでプロトコルメソッドを実装することはできません。
  4. そして今、あなたのDownloadManagerDownloadingFileProtocolの代わりに、特定のモデルとしての入力を取ることができ、今あなたが ダウンロードなど任意のモデルを作ることができます。
1

プロトコルを使用すると、1つのクラス/構造体を異なるものとして使用できます。たとえば、String構造体は、多くのプロトコルに対応しています。

Comparable 
CustomDebugStringConvertible 
Equatable 
ExtendedGraphemeClusterLiteralConvertible 
Hashable 
MirrorPathType 
OutputStreamType 
Streamable 
StringInterpolationConvertible 
StringLiteralConvertible 
UnicodeScalarLiteralConvertible 

これは、Stringが11種類の異なるものとして使用できることを意味します。メソッドが上記のプロトコルのいずれかをパラメータとして必要とする場合は、文字列を渡すことができます。

"しかし、私はプロトコルが持つすべてのメソッドを持つ神のクラスを作成することができます!"あなたは主張した。覚えておいてください。あなたはSwiftの1つのクラスだけを継承することができます。多重継承は非常に危険なので、コードを非常に複雑にすることができます。

また、プロトコルを使用すると、クラスのカスタム動作を定義できます。 Stringhashcodeメソッドは、Intのメソッドと同じではありません。しかし、これらは両方ともこの機能と互換性があります:

func doStuff(x: Hashable) { 

} 

それはプロトコルの本当の不思議です。

最後に重要なのは、プロトコルです。です。プロトコルは、「一種の」または「として使用できる」という関係を表します。 XをYとして使うことができるとき、XはプロトコルYに従うのが理にかなっています。

2

ほとんどの場合、タイプの階層です。 RedColorful を拡張 - - CubeShape

  • 異なる色を拡張

    • 異なる形状:あなたがGlowingRedCubeを表すオブジェクトを持っていますが、あなたが気に汎用コードの多くで使用されているタイプを持つようにしたいとしましょう照明の
    • 異なるタイプ - Glowingあなたが困っているIlluminated

    を拡張します。 GlowingRedCubeGlowingCubeShapeまで拡張されていますが、非常に幅広いクラスが用意されていますし、柔軟性のないものもあります(SoftRedCubeを作りたければどうしたらいいでしょうか? )

    Cubeを持っていて、イルミネーションとシェイプがプロパティになっている可能性がありますが、コンパイラのタイプチェックがうまくいかない場合:Room.lightUp()メソッドを持っていて、それを渡す必要がありますCubeの場合は、そのタイプに照明が含まれているかどうかを確認する必要があります。 Illuminatedしか渡すことができないなら、コンパイラは試してみるとすぐにあなたを止めるでしょう。

    プロトコルでは、これを分離することができます。は、Illuminatedプロトコル、Colorfulプロトコル、およびShapeプロトコルを実装できます。プロトコル拡張のために、機能のデフォルトの実装を含めることができるので、それを接続するために階層のレベルを選択する必要はありません。

    struct GlowingRedCube: Shape, Colorful, Illuminated { 
    // .. 
    } 
    

    効果的に、プロトコルを使用すると、そのオブジェクトが何をするかにかかわらず、オブジェクトにビヘイビアを付けることができます。つまり、デリゲートやデータソースプロトコルのようなものに使用されている理由です。ほとんどの場合、ViewControllerにそれらのオブジェクトを添付しても、基礎となるオブジェクトは関連性がないため、実装方法について柔軟にすることができます。

    Swiftのプロトコルは基本的なものよりもはるかに優れています。クラス、構造体、列挙型などのさまざまなコード構造に接続できるため、非常に強力です。これにより、プログラミングプロトコルに最初に近づくことができます。このアプローチには、WWDC last yearという素晴らしいビデオがありますが、いくつかの異なるオブジェクト構造を最初に試してみて、問題を感じるのに役立ちます。

  • 9

    クラスとプロトコルは直交する概念です。プロトコルはクラスツリー全体を切断し、異種の祖先と1つ以上のクラスを結合します。

    おそらく、もっと簡単に言えば:

    • "クラス" オブジェクトが何であるかを定義します。
    • "protocol"はオブジェクトが持つ動作を定義します。

    ですから、クラスの車を持っている:

    class Car { 
        var bodyStyle : String 
    } 
    

    とクラス色:

    class Color { 
        var red : Int 
        var green : Int 
        var blue : Int 
    } 
    

    は今、多かれ少なかれ明らかに色と車は完全に無関係です、しかし、のは、私を想定しましょうどちらか一方を文字列に簡単に変換できるようにしたいので、次のようにデバッグすることができます:

    print(Car(...)) 
    
    まさにこの目的のため

    又は

    print(Color(...)) 
    

    、スウィフト言語ので、我々は次に、車がそのプロトコルを使用して印刷することができる宣言することができるプロトコルCustomStringConvertibleを定義:

    extension Car : CustomStringConvertible { 
        var description : String { get { return "Car: \(bodyStyle)" } } 
    } 
    

    及び色並びに:

    extension Color : CustomStringConvertible { 
        var description : String { get { return "Color: \(red) \(green) \(blue)" } } 
    } 
    

    私は各クラスに1つの印刷方法が必要でしたが、今は1つの印刷方法が必要ですIKE:クラスがプロトコルを実装することを宣言すると、私は、彼らが実装され、(おそらく)期待されます何をしていることを知って、プロトコルのメソッドを使用することができます約束ですので

    func print(data:CustomStringConvertible) { 
        let string = data.description 
        ... bunch of code to actually print the line 
    } 
    

    これが可能です。

    +0

    でも、ObjCの複数のプロトコルに準拠することはできませんでしたか?スウィフトはどのように違うのですか? – Honey

    関連する問題