web-dev-qa-db-ja.com

クラスを拡張し、javaでインターフェースを実装します

interface Bouncable{ } 
interface Colorable extends Bouncable{ } 
class Super implements Colorable{ } 
class Sub extends Super implements Colorable {} // Ok (case -1)

だが、

class Sub implements Colorable extends Super {} // error (case -2)

なぜcase-2コンパイルエラーが表示される{ expected。なぜ ??ただし、case-1はエラーなしで実行されます。

17
Ravi

extendsimplementsの前に移動する必要があります。

class Sub extends Super implements Colorable {}
34
yegor256

クラス宣言で拡張が実装に先行する理由を示す例がありますが、

インターフェース:

public interface IParent {
    void getName();
    void getAddress();
    void getMobileNumber();
}

抽象クラス:

public abstract class Parent {
    public abstract void getAge();
    public void getName(){
        System.out.print("the parent name");
    }
}

子クラス:

public class Child extends Parent implements IParent {

    @Override
    public void getAddress() {
       System.out.print(" Child class overrides the Parent class getAddress()");
    }

    @Override
    public void getMobileNumber() {
        System.out.print(" Child class overrides the Parent class getMobileNumber()");
    }

    @Override
    public void getAge() {
        //To change body of implemented methods use File | Settings | File Templates.
    }
}

インターフェースと抽象クラスの両方に同じメソッドgetName()がある場合、抽象クラスではメソッドに実装があります。

実装しようとすると、クラスがインターフェイスのすべての抽象メソッドをオーバーライドすることが必須になり、メソッドgetName()の実装をすでに持っている抽象クラスを拡張しようとしています。

childクラスのインスタンスを作成し、getName()メソッドを次のように呼び出したとき

Child child = new Child();
child.getName();

同じメソッドgetName()には2つの実装があるため、子がどのメソッド実装を呼び出すかについて競合が発生します。

この競合を避けるために、最初に拡張し、後でインターフェースを実装することが必須になりました。

そのため、抽象クラスがインターフェイスと同じメソッドを持ち、抽象クラスがすでにメソッドを実装している場合、子クラスについてはそのメソッドをオーバーライドする必要はありません

5
ravikumar

これは、[〜#〜] jls [〜#〜]の仕様によるものです。また、Javaでクラスを宣言しようとすると、特定の要素の順序があります。

  • publicprivateなどの修飾子.
  • クラス名。慣例により大文字で始まる最初の文字。
  • キーワードextendsが前にあるクラスの親(スーパークラス)の名前(ある場合)。クラスは、1つの親のみを拡張(サブクラス)できます。
  • キーワードimplementsが前にある場合、クラスによって実装されるインターフェースのコンマ区切りリスト。クラスは複数のインターフェイスを実装できます。
  • 中括弧で囲まれたクラス本体、{ }

参照:

http://docs.Oracle.com/javase/tutorial/Java/javaOO/classdecl.html

1
Juvanis

JLS Syntax Page のクラス定義の構文は次のとおりです。

NormalClassDeclaration: 
    class Identifier [TypeParameters] [extends Type] [implements TypeList] ClassBody

構文規則を単純化するために、それらを交換可能にしたわけではないと思います。

交換可能にするには、おそらく次のようなものが必要です。

NormalClassDeclaration: 
    class Identifier [TypeParameters] [ExtendsImplements] ClassBody

ExtendsImplements:
    [extends Type] [implements TypeList] | [implements TypeList] [extends Type]

または最悪の場合、Extendsを使用するためにImplementsORを宣言する必要があります。

解析ルールを乱雑にする価値があることはそれほど重要ではないと思います。

1
Aviram Segal

Javaにルールがあります。インターフェイスを実装してクラスを拡張する場合は、最初にクラスを拡張してからインターフェイスを実装する必要があります

interface A{}
class super{}

class sub extends super implements A {}

Javaコンパイラがクラスをバイトコードに変換する場合、最初に親クラスを参照する必要があります。これは、クラスの基礎となる実装が、親クラスのバイトコード関連するメソッドとフィールド次に、子クラス関数のコードへのポインターを追加します-その一部は「implements」キーワードで必須です。

親クラスはコンパイル可能である必要があるため、コンパイラがそのクラスが何であるかを事前に知っていれば簡単です。さらに、1つのクラスのみを拡張できますが、任意の数のインターフェイスを実装できます。 extendsキーワードを任意の数のimplements命令に混ぜることができる場合、コンパイル時間が長くなります。コンパイラは開発時間を短縮するためにできるだけ早く失敗したいので、この選択は論理的です。さらに、同じ理由でクラスについて明確に考えるのに役立ちます。

0

このようにしなければなりません。 1つのクラスのみを拡張できますが、複数のインターフェイスをコンマで個別に実装できます。実装の前に最初に拡張機能を使用する方が読みやすい

class Sub extends Super implements Colorable
0
Suranga