コンピューティングにおいて、インターフェースとは、コンピュータシステムの2つ以上の独立したコンポーネントが情報を交換する共有境界のことです。情報交換は、ソフトウェア、コンピュータハードウェア、周辺機器、人間、およびこれらの組み合わせの間で行われることがあります。[ 1 ]タッチスクリーンなどの一部のコンピュータハードウェアデバイスは、インターフェースを介してデータの送受信の両方を行うことができますが、マウスやマイクなどの他のデバイスは、特定のシステムにデータを送信するためのインターフェースのみを提供する場合があります。[ 2 ]

ハードウェア インターフェースは、さまざまなバス、ストレージ デバイス、その他のI/Oデバイスなど、多くのコンポーネントに存在します。ハードウェア インターフェースは、インターフェース上の機械的、電気的、論理的な信号と、それらをシーケンスするためのプロトコル (シグナリングと呼ばれることもあります) によって記述されます。[ 3 ] SCSIなどの標準インターフェースは、I/Oデバイスなどのコンピューティング ハードウェアの設計と導入を、コンピューティング システムの他のコンポーネントの設計と導入から分離し、それによってユーザーと製造業者がコンピューティング システムの実装において大きな柔軟性を得られるようにします。[ 3 ]ハードウェア インターフェースは、複数の電気接続によってデータの一部を同時に伝送する並列接続と、データが一度に1ビットずつ送信される直列接続にすることができます。 [ 4 ]
ソフトウェアインターフェースは、さまざまな「レベル」のさまざまなタイプのインターフェースを指す場合があります。たとえば、オペレーティングシステムはハードウェアとインターフェースする場合があります。オペレーティングシステム上で実行されるアプリケーションやプログラムは、データストリーム、フィルタ、パイプラインを介して相互作用する必要がある場合があります。 [ 5 ]オブジェクト指向プログラムでは、アプリケーション内のオブジェクトはメソッドを介して相互作用する必要がある場合があります。[ 6 ]
設計の重要な原則は、デフォルトではすべてのリソースへのアクセスを禁止し、明確に定義されたエントリ ポイント、つまりインターフェースを介してのみアクセスを許可することです。[ 7 ]ソフトウェア インターフェースは、基盤となるコンピュータ システムのコンピュータ リソース (メモリ、CPU、ストレージなど) へのアクセスを提供します。ソフトウェアによるこれらのリソースへの直接アクセス (つまり、適切に設計されたインターフェースを介さないアクセス) は、機能性と安定性に重大な影響 (時には壊滅的な影響) を与える可能性があります。
ソフトウェアコンポーネント間のインターフェースは、定数、データ型、プロシージャの種類、例外仕様、メソッドシグネチャを提供できます。場合によっては、パブリック変数もインターフェースの一部として定義されます。[ 8 ]
ソフトウェアモジュールAのインターフェースは、そのモジュールの実装とは意図的に別個に定義されています。実装には、インターフェースで記述されたプロシージャやメソッドの実際のコード、およびその他の「プライベート」変数、プロシージャなどが含まれます。例えばAのクライアントである別のソフトウェアモジュールBは、公開されたインターフェースを介してのみAとやり取りすることが義務付けられています。この構成の実用的な利点の1つは、 Aの実装を同じインターフェースの別の実装に置き換えてもBが動作しなくなることはないということです。Aが内部的にインターフェースの要件をどのように満たしているかはBにとって重要ではなく、Bはインターフェースの仕様のみに関心があります。(リスコフの置換原則も参照してください。)
オブジェクト指向言語、特に完全な多重継承を持たない言語では、クラスの抽象化として機能する抽象型を定義するためにインターフェースという用語が使われます。インターフェースにはデータは含まれませんが、メソッドシグネチャとして動作を定義します。そのインターフェースに対応するすべてのメソッドのコードとデータを持ち、それを宣言しているクラスは、そのインターフェースを実装していると言われます。 [ 9 ]さらに、単一継承言語であっても、複数のインターフェースを実装できるため、同時に異なる型になることができます。 [ 10 ]
インターフェースは型定義の一種です。オブジェクトが交換される可能性のある場所(例えば、関数やメソッド呼び出しなど)では、交換されるオブジェクトの型を、特定のクラスを指定するのではなく、実装されているインターフェースまたは基底クラスのいずれかで定義できます。このアプローチにより、そのインターフェースを実装するクラスであればどれでも使用できます。例えば、最終的な実装が利用可能になる前に開発を進めるために、ダミーの実装を使用することができます。また、テスト中に偽の実装やモック実装を代用することもできます。このようなスタブ実装は、開発プロセスの後半で実際のコードに置き換えられます。
通常、インターフェースで定義されたメソッドにはコードが含まれていないため、それ自体を呼び出すことはできません。呼び出されたときに実行されるように、抽象コード以外のコードで実装する必要があります。「 」という名前のインターフェースは、と という2 つのメソッドを定義する場合があります。これは、とのように、さまざまな方法で実装できます。前者は固定サイズのデータ構造を扱うため高速ですが、後者はサイズ変更可能なデータ構造を使用するため、速度がやや低下します。Stackpush()pop()FastStackGenericStack
インターフェースには多くのメソッドが含まれることがありますが、1つだけ、あるいはまったく含まれない場合もあります。たとえば、Java言語では、単一のメソッドを持つインターフェースが定義されています。さまざまな実装が、、、、、、など、さまざまな目的で使用されています。などのマーカー インターフェースにはメソッドがまったく含まれておらず、リフレクションを使用した汎用処理に実行時情報を提供する役割を果たします。[ 11 ]Readableread()BufferedReaderFileReaderInputStreamReaderPipedReaderStringReaderSerializable
インターフェースの使用により、インターフェースへのプログラミングと呼ばれるプログラミングスタイルが可能になります。このアプローチの背後にある考え方は、内部実装の詳細ではなく、使用するオブジェクトのインターフェースに基づいてプログラミングロジックを構築することです。インターフェースへのプログラミングは、実装の詳細への依存を減らし、コードの再利用性を高めます。[ 12 ]
この考え方を極端に推し進めると、制御の反転によって、コンテキストが、作業を実行するために使用されるインターフェースの具体的な実装をコードに注入できるようになります。
ユーザーインターフェースとは、コンピュータと人間との間の相互作用の接点であり、ユーザーとコンピュータシステムの間でデータが転送される、あらゆる種類の相互作用様式(グラフィック、サウンド、位置、動きなど)を含みます。
インターフェースのみに依存するようになれば、実装から切り離されます。つまり、実装は変更可能であり、これは健全な依存関係です。たとえば、テスト目的で、重いデータベース実装を軽量なモック実装に置き換えることができます。幸いなことに、今日のリファクタリングのサポートにより、事前にインターフェースを作成する必要はなくなりました。問題を完全に理解したら、具体的なクラスからインターフェースを抽出できます。意図したインターフェースは、「インターフェースの抽出」リファクタリングを一度行うだけで得られます。
まず、Serializableインターフェースについて説明します。これはマーカーインターフェースであり、メソッドはありません。