Понимание цели абстрактных классов в Java - PullRequest
13 голосов
/ 08 февраля 2012

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

public abstract class A {

    protected abstract void method1(); 

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

public class B extends A {

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

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

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

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

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

ВОПРОСЫ:

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

Ответы [ 8 ]

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

@ Override

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

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

Но не стоит слишком беспокоиться об этом.

Абстрактный класс против интерфейса

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

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

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

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, чтобы реализовать его еще более эффективным способом (представьте, что сравнивать его дорого).Но есть сценарии, когда вы хотите предоставить базовую уже реализованную функциональность (и тогда, когда абстрактные классы лучше, чем интерфейсы) или когда вы хотите принудительно реализовать некоторую реализацию (тогда, когда ключевое слово final показывается полезным).

4 голосов
/ 08 февраля 2012

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

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

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

2 голосов
/ 08 февраля 2012

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

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

Также нельзя создавать экземпляры абстрактных методов (ни для интерфейсов).

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

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

1 голос
/ 08 февраля 2012

What is the purpose of @Override keyword

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

So what is the difference to implementing an interface?

Little.Iterface - это класс, в котором все методы являются абстрактными.Кроме того, допускается только один родительский класс, в то время как это может быть несколько интерфейсов.Также вы можете помещать члены в класс, но не в интерфейс.

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

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

1 голос
/ 08 февраля 2012

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

Четкость.

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

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

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

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

0 голосов
/ 22 мая 2018

Эта статья содержит несколько хороших понятий (и примеров) относительно названия вашего вопроса.

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

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

По сути,Цель Abstract Classes - определить класс с методами, которые:

  • должны быть объявлены (абстрактно) в подклассе
  • могут использоваться необязательно (неабстрактно) в подклассе


Дополнительный комментарий

  • Несколько лет назад я разработал приложение для Android (Java, а не Kotlin),и во время использования многих библиотек я испытывал поведение расширения моих классов с помощью абстрактных классов, и из-за поведения этого типа класса Android Studio автоматически добавлялась в мой класс.код, все абстрактные методы , которые были частью абстрактного класса , который я расширял.
0 голосов
/ 08 февраля 2012

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

public abstract class A {

    protected abstract void method1(int val); 

    protected void method2() { 
        System.out.println("This is Class A's 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's implementaiton of A's method");
        //Here you may do this class specific manipulation on val.
    } 
}  

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...