Какова важность абстрактного класса, который происходит от другого абстрактного класса - PullRequest
8 голосов
/ 29 марта 2019

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

Я искал примеры кодов, но они показывают только реализацию без объяснения им:

public abstract class Beverage {

   String description = "Beverage";

   public String getDescription(){
      return description;
   }
     public abstract double cost();

 }

// abstract class CondimentDecorator 
   public abstract class CondimentDecorator extends Beverage {

       @Override
       public abstract String getDescription();
 }

Как видите, абстрактный класс CondimentDecorator не реализует все функции в Beverage абстрактном классе.Он реализует только функцию getDescription().Но если бы CondimentDecorator был конкретным, то потребовалось бы реализовать все функции внутри Beverage абстрактного класса.

Ответы [ 3 ]

4 голосов
/ 29 марта 2019

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

По аналогии с реальным миром.
Представьте, что у вас есть класс Vehicle.Это может быть любое транспортное средство: автомобиль, самолет, автобус, велосипед, что угодно.Это твой абстрактный класс.Вы можете использовать это сейчас?Нет, потому что вы не знаете, нужно ли нажимать педали или поворачивать колесо.
Теперь вы создаете другой класс, скажем, Car extends Vehicle.Вы можете использовать это сейчас?Возможно, но вы до сих пор не знаете, грузовой это или легковой автомобиль.Но вы знаете, что у него есть рулевое колесо.
И, наконец, когда вы создаете еще один класс, скажем, MySuperPassengerCar extends Car, вы точно знаете, что это за объект, как его можно использовать и какими методами он обладает.

2 голосов
/ 29 марта 2019

Абстрактный класс определяет абстрактные методы. Любой класс, расширяющий другой класс, расширяет суперкласс, добавляя больше поведения. Если дочерний класс является абстрактным, он может добавить некоторое абстрактное поведение.

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

Давайте рассмотрим пример ниже.

public abstract class SuperAbstract {
      public void nonAbstract(){
            // some code
      }
      public abstract void contract();
}

public abstract class SubAbstract extends SuperAbstract{
       public void additionalNonAbstract()
             // some code
        }
        public abstract void additionalContract();
 }

public class Concrete extends SubAbstract{
       public void contract(){
             // implementation
       }
       public void additionalContract(){
               //implementation
       }
}

// although below is allowed and sometimes when we use an external library then this is one of the way but still this is not a good practice. 
// dependencies should be on abstractions only and not on concrete implementation
public abstract class AnotherAbstract extends Concrete{
       public void someMethod(){
             //some code
       }
       public abstract void oneMoreContract();
}

public class ConcreteA extends AnotherAbstract{
        public void oneMoreContract(){
               //some implementation
        }
}

Теперь обратите внимание, что всего мы определили 3 контракта, а ConcreteA имеет все реализации. Также обратите внимание, что поскольку Concrete предоставляет реализации для методов contract и additionalContract, следовательно, эти реализации наследуются ConcreteA

Код потребителя может легко зависеть от абстракции. Давайте посмотрим на это в коде пользователя (код потребителя)

  public class Consumer{
      public void m1(SuperAbstract c)
             c.contract();
             c.nonAbstract();
     }
     public void m2(AnotherAbstract c){
          c.contract();
          c.nonAbstract();
          c.oneMoreContract();
          c.additionalContract();
    }
 }

Теперь давайте посмотрим код подключения, обеспечивающий зависимости

 public class Main{
       public static void main(String[] args){
            Consumer c = new Consumer();
             c.m1(new Concrete());
             c.m1(new ConcreteA());
             c.m2(new ConcreteA());
     }
}
1 голос
/ 29 марта 2019

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

...