2016-03-03 32 views
5

は、ここに私の問題を示す簡単な例です:SingleTaskデフォルトのインターフェイスメソッドを実装する必要がありますか?

import java.util.List; 

public interface SingleTask extends List<Runnable>, Runnable { 
    default Runnable get(final int x) { 
     if (x != 0) { 
      throw new IndexOutOfBoundsException(); 
     } 
     return this; 
    } 

    default int size() { 
     return 1; 
    } 
} 

import java.util.AbstractList; 

public class MyTask extends AbstractList<Runnable> implements SingleTask { 
    @Override 
    public void run() { 
     System.out.println("hello"); 
    } 
} 

私はAbstractListからのみ抽象メソッドな方法getsize、の実装を提供します。

The type MyTask must implement the inherited abstract method AbstractCollection.size()

または

MyTask.java:3: error: MyTask is not abstract and does not override abstract method get(int) in AbstractList

は(コンパイラに依存する):しかし、私は MyTaskをコンパイルするとき、私はまだのようなエラーが発生します。なぜ私はこれらのエラーを

  1. 取得しています:私は、だから私は二つの質問をしているのjava 8

    を使用して、当然のことながら、午前?私はそれがデフォルトの実装を認識することを期待していました。

  2. そのように動作するはずがない場合は、コード全体をコピーしないでMyTaskの2つの方法を使用する最も簡単な方法は何ですか?またListのすべてのメソッドを実装するためにSingleTask実装を強制
+1

タスクを 'List 'に拡張しないでください(意味的にはどういう意味ですか?)、 'publicリスト getRunnables();'メソッドを使ってインタフェース 'Task'を作成してください。それに失敗した場合、単純に 'SingleTask'をインターフェースではなく抽象クラスにしてください。 – biziclop

+1

Eclipseは 'size()'が実装されていないことに気づいています。これはおそらくEclipseのバグです。 'javac' 1.8.0_51は実装されていない' get(int) 'で窒息しています。それは実装されていません。 – Tunaki

+0

@biziclopこれはタスクのリストになっているはずです。 SingleTaskはシングルトンの実装です – aditsu

答えて

6

は非常にエレガントではなく、デフォルトの方法は、あなたのSingleTaskインターフェースがどのように見える特性のようなエンティティを定義するために使用されることを意味するものではありません。

デフォルトのメソッドとしての特性が悪い考えである理由はいくつかあります。もっとも明白なのは、実装者がデフォルトメソッドを単にオーバーライドして特性を損なうことができるということです。

は、そして、これはまさに、ここで何が起こっているかである:AbstractListが明示的にabstractとしてget()size()を宣言するので、それはむしろあなたがスーパーインタフェースで持っていたかもしれないデフォルトの実装よりも、それらを継承しますSingleTaskを意味します。

JLS 8.4.8

最も簡単な解決策は、おそらくこれです心の中ですべてのことをベアリング

A class C inherits from its direct superclass and direct superinterfaces all abstract and default (§9.4) methods m for which all of the following are true:

...

  • No concrete method inherited by C from its direct superclass has a signature that is a subsignature of the signature of m.

public abstract class SingleTask extends AbstractList<Runnable> implements Runnable { 
    @Override 
    public final Runnable get(final int x) { 
     if (x != 0) { 
      throw new IndexOutOfBoundsException(); 
     } 
     return this; 
    } 

    @Override 
    public final int size() { 
     return 1; 
    } 

    @Override 
    public abstract void run(); 
} 

その欠点は、あなたのタスクはSingleTaskを拡張しなければなりませんので、何かを拡張することができないということです、プラスの側では、彼らはListであるタスクに対処する必要はありませんが、彼らはrun()を実装する必要があります。

しかし長期的には、継承を超える構成と、単にランナブルのリストを返すだけのタスクを優先します。

+0

私はSingleTaskの実装者にもAbstractListを拡張するよう強制していませんでしたが、あなたのように見えます。また、SingleTaskをクラスにしました。これは、私がこれを使用したい場合、別のクラスを拡張することができないことを意味します。あなたは私の最初の質問に答えようとしなかった。 – aditsu

+1

@aditsu '私は、SingleTaskの実装者にもAbstractListを拡張するよう強制していませんでした。そうです、それが問題の原因です。私はそれをカバーするために私の答えを編集します。 – biziclop

+0

間違っていますが、私のコードでは、SingleTaskの実装者はListのメソッドを実装するだけで済みます。 AbstractListについてはSingleTaskには何もありません! – aditsu

2
  1. Why am I getting these errors? I was expecting it to recognize the default implementations.

@biziclopは正しくhis answerに記載されていると思います。要するに、はget(int)size()メソッドを抽象として宣言しているため、デフォルトの実装よりも優先されます(SingleTask)。

  1. If it's not supposed to work like that, then what's the simplest way to use those two methods in MyTask without copying the whole code?

最も簡単には、彼らがSingleTaskインターフェイスでデフォルトのメソッドに委譲するように、MyTaskget(int)size()メソッドをオーバーライドすることです:

public class MyTask extends AbstractList<Runnable> implements SingleTask { 

    @Override 
    public void run() { 
     System.out.println("hello"); 
    } 

    @Override 
    public Runnable get(int index) { 
     return SingleTask.super.get(index); 
    } 

    @Override 
    public int size() { 
     return SingleTask.super.size(); 
    } 
} 

このアプローチを使用すると、委任のようなものだろうをデフォルトの方法にSingleTaskで入力してください。私はこれが悪いことではないと思います(少なくとも、あなたは属性を使う必要はありません)。さらに、これらのメソッドを記述するのが理にかなっているので、どのインタフェースがデフォルトの実装を提供するかを選択できます。

関連する問題