web-dev-qa-db-ja.com

Javaのジェネリックパラメーターでメソッドをオーバーライドしますか?

クラスEmailMonitor.Javaによってサブクラス化された抽象クラスMonitor.Javaがあります。

メソッド:

_public abstract List<? extends MonitorAccount> performMonitor(List<? extends MonitorAccount> accounts)
_

Monitor.Javaで定義されており、EmailMonitor.Javaでオーバーライドする必要があります。

現在、次のようにEmailMonitor.Javaでメソッドをオーバーライドしています。

_@Override
public List<EmailAccount> performMonitor(List<EmailAccount> emailAccounts) {
    //...unrelated logic
    return emailAccounts;
}
_

ただし、これによりコンパイル時エラーが発生します。

Name clash: The method performMonitor(List<EmailAccount>) of type EmailMonitor has the same erasure as performMonitor(Lis<? extends MonitorAccount> emailAccounts) of type Monitor but does not override it

EmailAccountMonitorAccountのサブクラスなので、(少なくとも私の心の中で)この方法でオーバーライドすることは完全に理にかなっています。コンパイラが私のロジックに満足していないので、EmailMonitor.performMonitor()へのすべての呼び出しがEmailAccountのリストを受信することを確認するためのコンパイル時間チェックを維持しながら、これを正しく行うにはどうすればよいですか?他のタイプのMonitorAccountよりも

43
Robert Ngetich

いいえ、適切にオーバーライドされていません。オーバーライドは、基本クラスへの有効な入力に対処できることを意味します。クライアントがこれを行うとどうなるかを考えてみましょう:

Monitor x = new EmailMonitor();
List<NonEmailAccount> nonEmailAccounts = ...;
x.performMonitor(nonEmailAccounts);

あなたの説明を与えられたコンパイル時エラーを与えるはずのものはそこにはありません-しかし、それは明らかに間違っています。

Monitorは監視できるアカウントのタイプで一般的である必要があるため、EmailMonitorMonitor<EmailAccount>を拡張する必要があります。そう:

public abtract class Monitor<T extends MonitorAccount>
{
    ...
    public abstract List<? extends T> performMonitor(
        List<? extends T> accounts);
}

public class EmailMonitor extends Monitor<EmailAccount>
{
    @Override
    public abstract List<? extends EmailAccount> performMonitor(
        List<? extends EmailAccount> accounts)
    {
        // Code goes here
    }
}

ただし、performMonitor呼び出しのジェネリックについて慎重に検討する必要があるかもしれません-戻り値は何を意味するのですか?

35
Jon Skeet

ここに私自身の解決策があります。これは、ジョンスキートが試みたのと同じことだと思います...タイプミスなしです(彼の回答に対する私のコメントを参照してください)。

の Monitor.Java クラス:

public abstract class Monitor <T extends MonitorAccount> {
  ...
  public abstract List<T> performMonitor(List<T> accounts);
  ..
}

EmailMonitor.Java

public class EmailMonitor extends Monitor<EmailAccount> {
  ...
  public List<EmailAccount> performMonitor(List<EmailAccount> emailAccounts) {
    ..//logic...logic...logic
    return emailAccounts;
  }
  ...
}

この構成では、 EmailMonitor.performMonitor() コンパイル時に常にリストを受け取ることを確認します メールアカウント 私の他のタイプではなく FTPAccount、DBAccount、 など...生のリストを受信/送信し、必要な型を強制する必要があり、実行時の型キャストの例外が発生する可能性がある代替案よりもはるかにクリーンです。

10
Robert Ngetich