わかりました、私の友人はプログラミングにおける「インターフェース」の意味について行ったり来たりしています。
「インターフェース」の最も良い説明は何ですか。
私にとってインターフェースはクラスの青写真ですが、これは最良の定義ですか?
わかりました、私の友人はプログラミングにおける「インターフェース」の意味について行ったり来たりしています。
「インターフェース」の最も良い説明は何ですか。
私にとってインターフェースはクラスの青写真ですが、これは最良の定義ですか?
回答:
インターフェースは、開発において過負荷で紛らわしい用語の1つです。
これは実際には抽象化とカプセル化の概念です。特定の「ボックス」について、そのボックスの「入力」と「出力」を宣言します。ソフトウェアの世界では、これは通常、(引数とともに)ボックスで呼び出すことができる操作と、場合によってはこれらの操作の戻り値の型を意味します。
それがしないことは、これらの操作のセマンティクスが何であるかを定義することですが、宣言の近くにそれらを文書化する(たとえば、コメントを介して)か、または適切な命名規則を選択することは一般的です(そして非常に良い習慣です)。それにもかかわらず、これらの意図が守られる保証はありません。
これは類推です:テレビがオフのときにテレビを見てください。そのインターフェースは、ボタン、さまざまなプラグ、および画面です。そのセマンティクスと動作は、入力(たとえば、ケーブルプログラミング)を受け取り、出力(画面への表示、サウンドなど)を持つことです。ただし、プラグインされていないテレビを見ると、期待されるセマンティクスがインターフェイスに投影されています。ご存知のように、テレビは電源を入れたときに爆発する可能性があります。ただし、その「インターフェース」に基づいて、取水口がないのでコーヒーがまったく出ないと考えられます。
オブジェクト指向プログラミングでは、インターフェイスは通常、そのインターフェイスを持つクラスのインスタンスが応答できる一連のメソッド(またはメッセージ)を定義します。
混乱を増すのは、Javaなどの一部の言語では、その言語固有のセマンティクスを持つ実際のインターフェースがあることです。たとえば、Javaでは、これは実装のないメソッド宣言のセットですが、インターフェイスも型に対応し、さまざまな型付け規則に従います。
C ++などの他の言語では、インターフェースはありません。クラス自体がメソッドを定義しますが、クラスのインターフェースは非プライベートメソッドの宣言と考えることができます。C ++のコンパイル方法により、実際に実装しなくてもクラスの「インターフェース」を持つことができるヘッダーファイルが得られます。また、純粋な仮想関数などを含む抽象クラスを持つJavaインターフェースを模倣することもできます。
インターフェイスは、クラスの青写真ではありません。設計図は、1つの定義では「詳細な行動計画」です。インターフェイスはアクションについて何も約束しません!混乱の原因は、ほとんどの言語で、メソッドのセットを定義するインターフェースタイプがある場合、それを実装するクラスが同じメソッドを「繰り返す」(ただし、定義を提供する)ため、インターフェースはスケルトンまたはクラスの概要。
次の状況を考慮してください。
ゾンビが突然あなたを攻撃するとき、あなたは大きな空の部屋の真ん中にいます。
武器はありません。
幸いなことに、仲間の生きている人間が部屋の出入り口に立っています。
「クイック!」あなたは彼に向かって叫びます。「私がゾンビを攻撃できる何かを投げてください!」
今考えてみてください:
あなたはあなたの友人がトスすることを選択するものを正確に指定しませんでした(あなたは気にしません)。
...ただし、次の条件が満たされていれば問題ありません。
それの何ができ翻弄さ(彼はあなたにソファを投げることはできません)
手に取ることができるものです(手裏剣を投げなかったことを祈りましょう)
それはあなたがゾンビの脳を打ち破るために使用できるものです(それは枕などを除外します)
野球のバットを手に入れてもハンマーを手に入れてもかまいません
。3つの条件を満たしていれば問題ありません。
要約すると:
あなたがインターフェースを書くとき、あなたは基本的に言っています:「私は何かが必要です...」
インターフェースは、実装者であるかユーザーであるかに応じて、準拠または付与する必要がある契約です。
「青写真」は良い言葉だとは思いません。設計図は、何かを構築する方法を示します。インターフェースは、具体的には、何かを構築する方法を伝えることを避けます。
インターフェースは、クラスとの対話方法、つまり、クラスがサポートするメソッドを定義します。
プログラミングでは、インターフェイスはオブジェクトの動作を定義しますが、実際には動作を指定しません。これは、特定のクラスが何かを実行できることを保証する契約です。
ここでこの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#はあなたに方法を通知します。
オブジェクト指向言語では当然関数はファーストクラスの市民ではないため、このメカニズムが使用されている理由は簡単に述べられています。あなたが見る、ようKnownNumber
やSecretNumber
番号を生成するために、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
に=>
なる->
)。
技術的には、オブジェクトと対話するための一連の方法(メソッド、プロパティ、アクセサ...語彙は、使用している言語によって異なります)としてインターフェイスを説明します。オブジェクトがインターフェースをサポート/実装している場合、インターフェースで指定されたすべての方法を使用して、このオブジェクトと対話できます。
意味的には、インターフェイスには、実行できることとできないこと(たとえば、メソッドを呼び出す順序)に関する規則や、やり取りした方法でオブジェクトの状態をどのように想定するかに関する規則を含めることもできます。はるか。
個人的にはテンプレートのようなインターフェースを見ています。インターフェイスにメソッドfoo()およびbar()の定義が含まれている場合、このインターフェイスを使用するすべてのクラスにメソッドfoo()およびbar()があることがわかります。
Man(ユーザーまたはオブジェクト)がいくつかの作業を実行したいと考えているとしましょう。彼は、企業(実装されたクラスを使用して作成された現実世界のオブジェクト)と契約を結ぶ中間者(インターフェース)に連絡します。いくつかの種類の作品が彼によって定義され、どの会社が彼に実装し、彼に結果を与えるでしょう。すべての企業が独自の方法で作業を実装しますが、結果は同じになります。このように、ユーザーは単一のインターフェースを使用して作業を完了します。インターフェイスは、実装する内部サブシステムによって内部的に定義されるコマンドがほとんどないシステムの可視部分として機能すると思います。
インターフェースは、それから継承するクラスが実装しなければならないものを定義します。このようにして、複数のクラスがインターフェースから継承でき、その継承のために、次のことができます。
詳細については、http://msdn.microsoft.com/en-us/library/ms173156.aspxを参照してください
私の意見では、インターフェースは、Javaで一般的に関連付けられているものよりも広い意味を持っています。「インターフェース」は、モジュールの制御/監視を可能にする、いくつかの一般的な機能を備えた利用可能な操作のセットとして定義します。
この定義では、クライアントがいくつかのモジュールであるプログラムインターフェイスとヒューマンインターフェイス(たとえばGUI)の両方をカバーするようにしています。
他の人がすでに述べたように、インターフェースは常に入力と出力の面でその背後にある契約を持っています。インターフェースは、操作の「方法」について何も約束しません。現在の状態、選択された操作、およびそのパラメーターを前提として、結果のいくつかのプロパティのみを保証します。
上記のように、「契約」と「プロトコル」の同義語が適切です。
インターフェースは、クラスによって公開されることが期待できるメソッドとプロパティで構成されます。
したがって、クラスCheetos Bag
がChip Bag
インターフェースを実装する場合、がCheetos Bag
他のとまったく同じように動作することを期待する必要がありますChip Bag
。(つまり、.attemptToOpenWithoutSpillingEverywhere()
メソッドを公開するなど)
従来の定義-インターフェースは、それを実装するクラスによって実装される必要があるメソッドを指定するコントラクトです。
インターフェースの定義は時間とともに変化しました。インターフェースにはメソッド宣言だけがあると思いますか?Java 5以降の静的な最終変数とデフォルトの定義についてはどうでしょうか。
複数の継承に関するダイヤモンドの問題が原因でJavaにインターフェースが導入されましたが、それが実際に彼らがしようとしていることです。
インターフェースは、多重継承の問題を回避するために作成された構成要素であり、抽象メソッド、デフォルトの定義、静的な最終変数を持つことができます。
インターフェイスは、一部のオブジェクト指向言語がアドホックなポリモーフィズムを実現する方法です。アドホックなポリモーフィズムは、異なる名前で動作する同じ名前の関数です。