異なるパッケージに同じ署名を持つ 2 つのインターフェイスを実装する
Go では、インターフェイスは、インターフェイスを実装する型のコントラクトを定義する方法を提供します。特定のインターフェイスを実装する型は、そのすべてのメソッドの実装を提供する必要があります。ただし、異なるパッケージに同一のメソッド シグネチャを持つインターフェイスを実装すると、混乱や不一致が生じる可能性があります。
次のシナリオを考えてみましょう:
<code class="go">// Package A package A type Doer interface { Do() string } func FuncA(doer Doer) { // Logic using doer.Do() } // Package B package B type Doer interface { Do() string } func FuncB(doer Doer) { // Logic using doer.Do() }</code>
ここで、メイン パッケージにタイプ C があると仮定します。 Do() の実装が異なる A.Doer と B.Doer の両方を実装します。 C のインスタンスを FuncA() に渡すと、A.Doer で定義された実装を利用して期待どおりに動作します。ただし、C を FuncB() に渡すと、Do() の実装が異なるため、ロジックが予期しない動作を引き起こします。
この問題に対処するには、次の 2 つの推奨アプローチがあります。
メソッドの型アサーション:
Go の FAQ によると、「名前のみで一致し、型の一貫性を要求するのは、Go の型システムを簡素化するための重要な決定でした。」したがって、Go はさまざまなシグネチャに基づくメソッドのオーバーロードをサポートしていません。ただし、メソッド タイプ アサーションを実行して、オブジェクトが特定のインターフェイス タイプを満たすかどうかを確認できます。例:
<code class="go">if _, ok := obj.(A.Doer); ok { // obj conforms to A.Doer // Use obj.Do() as desired }</code>
ラッパー タイプ:
または、目的のロジックで必要なインターフェイスを実装するオブジェクトの周囲にラッパー タイプを作成することもできます。たとえば、C をラップして A.Do() の特定の実装を提供する DoerA と、C をラップして B.Do() の実装を提供する DoerB を作成できます。このアプローチにより、適切なラッパー タイプを目的の関数に渡すことができ、正しいロジックが確実に実行されるようになります。
以上がGo の異なるパッケージで同じ署名を持つインターフェイスの実装を処理するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。