it-roy-ru.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 выполняется без ошибок. 

15
Ravi

extends должен идти перед implements:

class Sub extends Super implements Colorable {}
32
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 ().

Чтобы избежать этого конфликта, они сделали обязательным расширение сначала и реализацию интерфейса позже.

так что если абстрактный класс имеет тот же метод, что и в интерфейсе, и если абстрактный класс уже реализовал метод, то для дочернего класса нет необходимости переопределять этот метод 

3
ravikumar

Это связано со спецификацией в JLS. И есть определенный порядок элементов при попытке объявить класс в Java:

  • Модификаторы, такие как public, private и т.д.
  • Имя класса с начальной буквой, заглавной в соответствии с соглашением.
  • Имя родителя класса (суперкласса), если таковое имеется, предшествует Ключевое слово extends. Класс может расширять (подкласс) только одного Parent.
  • Разделенный запятыми список интерфейсов, реализуемых классом, если Any, с предшествующим ключевым словом implements. Класс может реализовать Более чем один интерфейс.
  • Тело класса, окруженное фигурными скобками, { }.

Ссылка:

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

1
Juvanis

Синтаксис для определения класса в Страница синтаксиса JLS is

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 и Implements, чтобы использовать OR.

Я думаю, что это не так важно, что стоит загромождать правила синтаксического анализа.

1
Aviram Segal

В Java есть правило: если вы хотите реализовать интерфейс и расширить класс, мы должны сначала расширить класс, а затем реализовать интерфейс.

interface A{}
class super{}

class sub extends super implements A {}

Когда компилятор Java превращает класс в байт-код, он должен сначала обратиться к родительскому классу. Это потому, что базовая реализация классов должна указывать на байт-код родительского класса, который содержит соответствующие методы и поля. Затем он добавляет указатели на код функций дочернего класса, некоторые из которых передаются по ключевому слову «Implements». 

Поскольку родительский класс должен быть компилируемым, проще, если компилятор заранее знает, что это за класс. Кроме того, вы можете расширить только один класс, но реализовать любое количество интерфейсов. Время компиляции увеличивается, если ключевое слово extends может смешиваться с любым количеством инструкций реализации. Компиляторы хотят как можно быстрее выйти из строя, чтобы уменьшить время разработки, поэтому этот выбор логичен. Кроме того, это помогает вам ясно думать о классе по той же причине. 

0
Hemanth Kasireddy

Вы должны сделать это так. Вы можете расширить только один класс, но вы можете реализовать несколько интерфейсов через запятую отдельно. было бы более удобным для читателя иметь расширение первым перед внедрением

class Sub extends Super implements Colorable
0
Suranga