Понимание цели абстрактных классов в Java

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

public abstract class A {

    protected abstract void method1(); 

    protected void method2() { 
        System.out.println("This is Class A method"); 
    } 
}

public class B extends A {

    @Override
    protected void method1() {
        System.out.println("This is B implementaiton of A method");
    } 
}  

и теперь, когда я тестирую их:

B b = new B();
b.method1();
b.method2();  

Я получаю ожидаемый результат:

This is B implementaiton of A method
This is Class A method

ВОПРОСЫ:

  • Какова цель ключевого слова @Override, потому что, если я его опускаю, это все еще работает одинаково.
  • Если я не реализую абстрактный метод, я получаю ошибку компиляции. Так в чем же отличие от реализации интерфейса?
  • Кроме того, я могу реализовать method2() в B. Затем выход изменяется на то, что используется в B. Не является ли это также переопределением метода родительского класса? Тогда в чем цель явного определения метода как абстрактного в классе A?

Ответ 1

@Override

@Override был введен в Java 5 (и немного расширен в Java 6). Это только информативное. В нем говорится: "Я предполагаю переопределить то, что уже существует в родительском классе или интерфейсе.

IDE, например Eclipse, может предупредить вас, если нет такого родительского метода (например, если вы неправильно используете имя). В этом случае ваш метод не будет вызван (из-за неправильного обращения).

Но не беспокойтесь о нем слишком много.

Абстрактный класс vs interface

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

Переопределить два метода

Да. В Java вы можете переопределить все методы, не являющиеся явно выраженными в родительском классе. Все в порядке. Если вы хотите сделать его немодифицированным, вы можете объявить его окончательным. Например, если вы хотите объявить заказ, вы можете:

public abstract class Ordering<X>
{
abstract boolean isLower(X a, X b);
abstract boolean isEquals(X a, X b);
   final boolean isGreater(X a, X b) {
      return !isLower(a, b) && !isEquals(a, b);
   }
}

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

Ответ 2

  • @Override не является ключевым словом, это необязательная аннотация, которая помогает компилятору проверить, что вы действительно переопределяете метод. Если вы скажете @Override, но нет способа переопределить, компилятор скажет вам, что вы, вероятно, сделали опечатку. Переименуйте method1 в method12, чтобы увидеть эффект.
  • Интерфейс не может иметь каких-либо реализаций, в то время как абстрактный класс может необязательно предоставлять реализации некоторых из его методов. Кроме того, интерфейсы не могут содержать данные.
  • Определение метода как абстрактного означает, что производный класс должен обеспечить реализацию. Не объявляя его абстрактным, говорят, что производные классы просто могут предоставлять свою собственную реализацию, но им это не нужно.

Ответ 3

Абстрактные классы позволяют хранить реализации базового уровня (наследование), а также создавать контракт, гарантирующий, что унаследованные классы будут реализовывать определенные функции (интерфейс) самостоятельно...

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

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

Ответ 4

Основное различие между абстрактными классами и интерфейсами состоит в том, что интерфейсы определяют интерфейс, а абстрактные классы также могут иметь реализацию и поля/свойства.

Абстрактный класс можно рассматривать как отношение IS-A (например, лошадь - животное). Для интерфейса в основном это функция, которую может иметь класс (например, INavigable, ISortable).

Также абстрактные методы не могут быть созданы (ни интерфейсы).

Функции переопределения должны показать, что функция имеет реализацию базового класса.

Также множественное наследование невозможно/рекомендуется с помощью классов, поэтому макс. использовать только один базовый класс и наследовать от интерфейсов для других функций.

Ответ 5

Какова цель ключевого слова @Override, потому что если я опускаю его, это все еще работает одинаково.

Четкость.

Если я не реализую абстрактный метод, я получаю ошибку компиляции. Итак, что разница в реализации интерфейса?

Интерфейсы не позволяют включать код.

Кроме того, я могу реализовать метод2() в B. Затем выходные изменения к тому, что используется в B. Не является ли это также переопределением родительского класса метод. Тогда в чем заключается цель явного определения метода абстрактно в классе А?

Да, это переопределение родительского метода. Обычно вы определяете метод как абстрактный, чтобы оставить реализацию для ребенка (который ДОЛЖЕН реализовать его или быть абстрактным). Если это не абстрактно, вы должны его реализовать.

Ответ 6

What is the purpose of @Override keyword

Это более поздняя добавка Java, которая предназначена для слабого самоконтроля. Это аннотация, т.е. Класс библиотеки, а не ключевое слово.

So what is the difference to implementing an interface?

Мало. Iterface - это класс, в котором все методы абстрактны. Кроме того, разрешен только один родитель класса, в то время как он может быть несколькими интерфейсами. Также вы можете поместить элементы в класс, но не в интерфейс.

Then what is the purpose of explicitly Defining a method abstract in Class A?

Вы должны объявить его абстрактным, только если у него нет тела. Для JVM требуется знать, что все потомки будут иметь его.

Ответ 7

Реальное использование приходит в картину, когда вы реализуете несколько классов, и метод method1 вызывается из метода2. В этом случае после выполнения метода2 будет выполняться метод1 в соответствующем классе.

public abstract class A {

    protected abstract void method1(int val); 

    protected void method2() { 
        System.out.println("This is Class A method");
        //Let us I calculated something here, may be sum of two ints 
        method1(//pass above calculated int);
    } 
}

public class B extends A {

    @Override
    protected void method1(int val) {
        System.out.println("This is B implementaiton of A method");
        //Here you may do this class specific manipulation on val.
    } 
}  

Как и в классе C, вы можете манипулировать общими вычислениями.