オブジェクト指向プログラミングにおける「インターフェース」の定義は何ですか


108

わかりました、私の友人はプログラミングにおける「インターフェース」の意味について行ったり来たりしています。

「インターフェース」の最も良い説明は何ですか。

私にとってインターフェースはクラスの青写真ですが、これは最良の定義ですか?


1
:ないだまされやすい人が、それはこの質問に多くの光を当てるstackoverflow.com/questions/444245/...
rmeador

一般的な言葉ですが、私にとっても同じことを意味します。これは、特定の、またはより抽象的なエンティティの壁のようなもので、外部にいくつかの入力ポイントを提供し、内部操作の知識なしにそれらに出力を与えます。OOPで下位レベルから上位レベルのクラスを定義することは、抽象化と呼ぶことができると思います。
ikbal 2016年

回答:


178

インターフェースは、開発において過負荷で紛らわしい用語の1つです。

これは実際には抽象化とカプセル化の概念です。特定の「ボックス」について、そのボックスの「入力」と「出力」を宣言します。ソフトウェアの世界では、これは通常、(引数とともに)ボックスで呼び出すことができる操作と、場合によってはこれらの操作の戻り値の型を意味します。

それがしないことは、これらの操作のセマンティクスが何であるかを定義することですが、宣言の近くにそれらを文書化する(たとえば、コメントを介して)か、または適切な命名規則を選択することは一般的です(そして非常に良い習慣です)。それにもかかわらず、これらの意図が守られる保証はありません。

これは類推です:テレビがオフのときにテレビを見てください。そのインターフェースは、ボタン、さまざまなプラグ、および画面です。そのセマンティクスと動作は、入力(たとえば、ケーブルプログラミング)を受け取り、出力(画面への表示、サウンドなど)を持つことです。ただし、プラグインされていないテレビを見ると、期待されるセマンティクスがインターフェイスに投影されています。ご存知のように、テレビは電源を入れたときに爆発する可能性があります。ただし、その「インターフェース」に基づいて、取水口がないのでコーヒーがまったく出ないと考えられます。

オブジェクト指向プログラミングでは、インターフェイスは通常、そのインターフェイスを持つクラスのインスタンスが応答できる一連のメソッド(またはメッセージ)を定義します。

混乱を増すのは、Javaなどの一部の言語では、その言語固有のセマンティクスを持つ実際のインターフェースがあることです。たとえば、Javaでは、これは実装のないメソッド宣言のセットですが、インターフェイスも型に対応し、さまざまな型付け規則に従います。

C ++などの他の言語では、インターフェースはありません。クラス自体がメソッドを定義しますが、クラスのインターフェースは非プライベートメソッドの宣言と考えることができます。C ++のコンパイル方法により、実際に実装しなくてもクラスの「インターフェース」を持つことができるヘッダーファイルが得られます。また、純粋な仮想関数などを含む抽象クラスを持つJavaインターフェースを模倣することもできます。

インターフェイスは、クラスの青写真ではありません。設計図は、1つの定義では「詳細な行動計画」です。インターフェイスはアクションについて何も約束しません!混乱の原因は、ほとんどの言語で、メソッドのセットを定義するインターフェースタイプがある場合、それを実装するクラスが同じメソッドを「繰り返す」(ただし、定義を提供する)ため、インターフェースはスケルトンまたはクラスの概要。


私はObjective-Cに関する本を読んでいますが、著者は「プロトコル」と「インターフェース」という用語を同じ意味で使用しているようです。「プロトコル」と「インターフェース」は同じものだと言ってもいいですか、それとも何か不足していますか?
Fazzolini 2015

1
「インターフェース」には「プロトコル」という言葉は使用しません。「プロトコル」という言葉は、アクションの実行方法に関する詳細レベルを意味します。「インターフェース」は、純粋な英語の定義を備えた優れた単語であり、厳密にそれを正確に説明しています。
OCDev

Windowsプログラミングインターフェースは非常に広く使用されているため、C ++でも、実装から切り離されたオブジェクトの方法で「インターフェース」を満たすことができます
ビクトリア

165

次の状況を考慮してください。

ゾンビが突然あなたを攻撃するとき、あなたは大きな空の部屋の真ん中にいます。

武器はありません。

幸いなことに、仲間の生きている人間が部屋の出入り口に立っています。

「クイック!」あなたは彼に向かって叫びます。「私がゾンビを攻撃できる何かを投げてください!」

今考えてみてください:
あなたはあなたの友人がトスすることを選択するものを正確に指定しませんでした(あなたは気にしません)。
...ただし、次の条件が満たされていれば問題ありません。

  • それの何ができ翻弄さ(彼はあなたにソファを投げることはできません)

  • 手に取ることができるものです(手裏剣を投げなかったことを祈りましょう)

  • それはあなたがゾンビの脳を打ち破るために使用できるものです(それは枕などを除外します)

野球のバットを手に入れてもハンマーを手に入れてもかまいません
。3つの条件を満たしていれば問題ありません。

要約すると:

あなたがインターフェースを書くとき、あなたは基本的に言っています:「私は何かが必要です...」


13
実際には、枕はまだ機能します。あなたはそれでゾンビを打つことができます。ゾンビの頭脳を打ち消しなさい...まあそれはパフォーマンスの問題であり、それは決してインターフェースの一部ではありません。
meustrus 2017

35

インターフェースは、実装者であるかユーザーであるかに応じて、準拠または付与する必要がある契約です。


1
私は実際には、ここでの無条件の契約は好きではありません。契約は、多くの場合、(契約による設計の場合のように)セマンティクスまたは動作を意味するためです。すべてのインターフェースが意味や動作を意味するわけではありません。たとえば、「壁の穴」は実際のインターフェースです。これをウィンドウとして、またはゴミ処理として、あるいは何かとして認識するかどうかは、あなたの解釈です。
ウリ

3
そうだね。インターフェイスは「メソッドシグネチャコントラクト」であり、指定されたメソッドの実装を保証します。所定の方法でそうであるかどうかは保証されません。
Erik Funkenbusch、

正確には、この定義についてさらに説明する必要があります。しかし、インターフェースは2つの部分の間の契約です。契約によるコード.... +1
matiasnj 2011

18

「青写真」は良い言葉だとは思いません。設計図は、何かを構築する方法を示します。インターフェースは、具体的には、何かを構築する方法を伝えることを避けます。

インターフェースは、クラスとの対話方法、つまり、クラスがサポートするメソッドを定義します。


1
私は、要求者が定義とは何かではなく、何であるかを尋ねたと思います。:)
Eugene Kuleshov

7

私にとってインターフェースはクラスの青写真ですが、これは最良の定義ですか?

いいえ。設計図には通常内部が含まれています。しかし、インターフェースは純粋にクラスの外側に見えるものについてのものです...より正確には、インターフェースを実装するクラスのファミリーです。

インターフェイスは、メソッドのシグネチャと定数の値、およびインターフェイスを実装するクラスとそれを使用するクラス間の(通常は非公式の)「動作規約」で構成されます。


6

プログラミングでは、インターフェイスはオブジェクトの動作を定義しますが、実際には動作を指定しません。これは、特定のクラスが何かを実行できることを保証する契約です。

ここでこのC#コードを検討してください。

using System;

public interface IGenerate
{
    int Generate();
}

// Dependencies
public class KnownNumber : IGenerate
{
    public int Generate() 
    {
        return 5;
    }   
}

public class SecretNumber : IGenerate
{
    public int Generate()
    {
        return new Random().Next(0, 10);
    }
}

// What you care about
class Game
{
    public Game(IGenerate generator) 
    {
        Console.WriteLine(generator.Generate())
    }
}

new Game(new SecretNumber());
new Game(new KnownNumber());

Gameクラスには秘密の番号が必要です。それをテストするために、秘密の番号として使用されるものを注入したいとします(この原理は制御の反転と呼ばれます)。

ゲームクラスは、実際に乱数を作成するものについて「オープンマインド」でありたいので、コンストラクターで「Generateメソッドを持つもの」を要求します。

まず、インターフェイスは、オブジェクトが提供する操作を指定します。見た目だけが含まれていますが、実際の実装は示されていません。これはメソッドのシグネチャです。従来、C#のインターフェイスにはIのプレフィックスが付いています。クラスはIGenerateインターフェイスを実装しています。これは、コンパイラが両方ともintを返し、呼び出されるメソッドを持っていることを確認することを意味しますGenerate。現在、ゲームは2つの異なるオブジェクトと呼ばれ、それぞれが適切なインターフェースを実装しています。他のクラスは、コードのビルド時にエラーを生成します。

ここで私はあなたが使用した青写真の類似に気づきました:

クラスは通常、オブジェクトの青写真と見なされます。インターフェースはクラスが行う必要があることを指定するので、それは確かにクラスの単なる青写真であると主張することができますが、クラスは必ずしもインターフェースを必要としないため、この比喩は壊れていると主張します。インターフェースを契約と考えてください。「それに署名する」クラスは、契約の契約条件に準拠するために法的に要求されます(コンパイラポリスによって施行されます)。これは、インターフェースで指定されていることを実行する必要があることを意味します。

これはすべて、JavaまたはC#の場合と同様に、一部のOO言語の静的型付けの性質によるものです。一方、Pythonでは別のメカニズムが使用されます。

import random

# Dependencies
class KnownNumber(object):
    def generate(self):
        return 5

class SecretNumber(object):
    def generate(self):
        return random.randint(0,10)

# What you care about
class SecretGame(object):
    def __init__(self, number_generator):
        number = number_generator.generate()
        print number

ここでは、どのクラスもインターフェースを実装していません。SecretGameクラスは渡されたオブジェクトを呼び出そうとするだけなので、Pythonはそれを気にしません。オブジェクトがgenerate()メソッドを持っている場合、すべてが正常です。そうでない場合:KAPUTT!この間違いはコンパイル時には見られませんが、実行時には見られるため、プログラムがすでにデプロイされて実行されている場合に発生する可能性があります。あなたがそれに近づく前に、C#はあなたに方法を通知します。

オブジェクト指向言語では当然関数はファーストクラスの市民ではないため、このメカニズムが使用されている理由は簡単に述べられています。あなたが見る、ようKnownNumberSecretNumber番号を生成するために、JUST関数が含まれています。実際にはクラスは必要ありません。したがって、Pythonでは、それらを捨てて、自分で関数を選択することができます。

# OO Approach
SecretGame(SecretNumber())
SecretGame(KnownNumber())

# Functional Approach

# Dependencies
class SecretGame(object):
    def __init__(self, generate):
        number =  generate()
        print number

SecretGame(lambda: random.randint(0,10))
SecretGame(lambda: 5)

ラムダは単なる関数であり、「インラインで」と宣言されています。デリゲートはC#でもまったく同じです。

class Game
{
    public Game(Func<int> generate) 
    {
        Console.WriteLine(generate())
    }
}    

new Game(() => 5);
new Game(() => new Random().Next(0, 10));

補足:後者の例は、Java 7まではこのようにはできませんでした。そこでは、この動作を指定する唯一の方法がインターフェースでした。ただし、Java 8ではラムダ式が導入されたため、C#の例をJavaに非常に簡単に変換できます(Func<int>java.util.function.IntSupplier=>なる->)。


4

技術的には、オブジェクトと対話するための一連の方法(メソッド、プロパティ、アクセサ...語彙は、使用している言語によって異なります)としてインターフェイスを説明します。オブジェクトがインターフェースをサポート/実装している場合、インターフェースで指定されたすべての方法を使用して、このオブジェクトと対話できます。

意味的には、インターフェイスには、実行できることとできないこと(たとえば、メソッドを呼び出す順序)に関する規則や、やり取りした方法でオブジェクトの状態をどのように想定するかに関する規則を含めることもできます。はるか。


2

個人的にはテンプレートのようなインターフェースを見ています。インターフェイスにメソッドfoo()およびbar()の定義が含まれている場合、このインターフェイスを使用するすべてのクラスにメソッドfoo()およびbar()があることがわかります。


2

Man(ユーザーまたはオブジェクト)がいくつかの作業を実行したいと考えているとしましょう。彼は、企業(実装されたクラスを使用して作成された現実世界のオブジェクト)と契約を結ぶ中間者(インターフェース)に連絡します。いくつかの種類の作品が彼によって定義され、どの会社が彼に実装し、彼に結果を与えるでしょう。すべての企業が独自の方法で作業を実装しますが、結果は同じになります。このように、ユーザーは単一のインターフェースを使用して作業を完了します。インターフェイスは、実装する内部サブシステムによって内部的に定義されるコマンドがほとんどないシステムの可視部分として機能すると思います。


1

インターフェースは、クラスの操作と内部の実装を分離します。したがって、いくつかの実装は多くのインターフェースを提供するかもしれません。

人々は通常、それをクラスのメソッドで利用可能でなければならないものの「契約」として説明します。

これは青写真ではありません。実装を決定するためです。完全なクラス定義は青写真と言えるでしょう。


1

インターフェースは、それから継承するクラスが実装しなければならないものを定義します。このようにして、複数のクラスがインターフェースから継承でき、その継承のために、次のことができます。

  • インターフェースのすべてのメンバーが派生クラスに実装されていることを確認してください(例外をスローするだけであっても)
  • 呼び出し元からクラス自体を抽象化します(クラスのインスタンスをインターフェイスにキャストし、実際の派生クラスが何であるかを知る必要なく、それと対話します)

詳細については、http://msdn.microsoft.com/en-us/library/ms173156.aspxを参照してください


1

私の意見では、インターフェースは、Javaで一般的に関連付けられているものよりも広い意味を持っています。「インターフェース」は、モジュールの制御/監視を可能にする、いくつかの一般的な機能を備えた利用可能な操作のセットとして定義します。

この定義では、クライアントがいくつかのモジュールであるプログラムインターフェイスとヒューマンインターフェイス(たとえばGUI)の両方をカバーするようにしています。

他の人がすでに述べたように、インターフェースは常に入力と出力の面でその背後にある契約を持っています。インターフェースは、操作の「方法」について何も約束しません。現在の状態、選択された操作、およびそのパラメーターを前提として、結果のいくつかのプロパティのみを保証します。


1

上記のように、「契約」と「プロトコル」の同義語が適切です。

インターフェースは、クラスによって公開されることが期待できるメソッドとプロパティで構成されます。

したがって、クラスCheetos BagChip Bagインターフェースを実装する場合、がCheetos Bag他のとまったく同じように動作することを期待する必要がありますChip Bag。(つまり、.attemptToOpenWithoutSpillingEverywhere()メソッドを公開するなど)


1

従来の定義-インターフェースは、それを実装するクラスによって実装される必要があるメソッドを指定するコントラクトです。

インターフェースの定義は時間とともに変化しました。インターフェースにはメソッド宣言だけがあると思いますか?Java 5以降の静的な最終変数とデフォルトの定義についてはどうでしょうか。

複数の継承に関するダイヤモンドの問題が原因でJavaにインターフェースが導入されましたが、それが実際に彼らがしようとしていることです。

インターフェースは、多重継承の問題を回避するために作成された構成要素であり、抽象メソッド、デフォルトの定義、静的な最終変数を持つことができます。

http://www.quora.com/Why-does-Java-allow-static-final-variables-in-interfaces-when-they-are-only-intended-to-be-contracts



弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.