здрасти Нека поговорим за абстрактни класове в Java.Конкретни примери за абстрактни класове в Java - 1

Защо класовете се наричат ​​"абстрактни"?

Вероятно се сещате Howво е абстракция — обсъдихме го по-рано :) Ако сте забравor, не се притеснявайте. Не забравяйте, че това е принцип на ООП, който казва, че когато проектирате класове и създавате обекти, трябва да представяте само основните свойства на обекта и да отхвърлите вторичните. Например, ако проектираме SchoolTeacherклас, височината вероятно няма да бъде необходимо свойство на учителя. Всъщност тази характеристика не е важна за учителя. Но ако създаваме BasketballPlayerклас, тогава височината ще бъде една от най-важните характеристики. Е, абстрактен класе най-абстрактният, "груб детайл" за група бъдещи класове. Заготовката не може да се използва директно — твърде е „груба“. Но той определя определено характерно състояние и поведение, което бъдещите класове - потомците на абстрактния клас - ще имат.

Примери за абстрактни класове в Java

Помислете за прост пример с автомобor:

public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;
  
   public abstract void gas();

   public abstract void brake();

   public String getModel() {
       return model;
   }

   public void setModel(String model) {
       this.model = model;
   }

   public String getColor() {
       return color;
   }

   public void setColor(String color) {
       this.color = color;
   }

   public int getMaxSpeed() {
       return maxSpeed;
   }

   public void setMaxSpeed(int maxSpeed) {
       this.maxSpeed = maxSpeed;
   }
}
Ето How изглежда най-простият абстрактен клас. Както виждате, нищо особено :) Защо може да ни трябва това? Първо, той предоставя най-абстрактното описание на обекта, от който се нуждаем - кола. Ключовата дума abstract означава нещо тук. В реалния свят няма такова нещо като „просто кола“. Има камиони, състезателни коли, седани, купета и SUV. Нашият абстрактен клас е просто "план", който по-късно ще използваме за създаване на конкретни класове автомобor.

public class Sedan extends Car {
  
   @Override
   public void gas() {
       System.out.println("The sedan is accelerating!");
   }

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }
  
}
В много отношения това е подобно на това, за което говорихме в уроците по наследство. Само че в този случай имахме Carклас, чиито методи не бяха абстрактни. Но такова решение има няколко недостатъка, които са фиксирани в абстрактни класове. Първо и най-важно, екземпляр на абстрактен клас не може да бъде създаден:

public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Error! The Car class is abstract!
   }
}
Създателят на Java е направил тази „функция“ нарочно. Още веднъж, запомнете: абстрактен клас е просто план за бъдещи "обикновени" класове . Не се нуждаете от копия на план, нали? По същия начин няма нужда да създаваме екземпляри на абстрактен клас :) И ако класът Carне беше абстрактен, тогава лесно бихме могли да създадем негови екземпляри:

public class Car {

   private String model;
   private String color;
   private int maxSpeed;
  
   public void go() {
       // ...some logic
   }

   public  void brake() {
       // ...some logic
   }
}


public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // This is okay. The car is created.
   }
}
В момента нашата програма има няHowва неразбираема кола. Не е камион, не е състезателна кола и не е седан, но не е съвсем ясно Howво е. Това е "просто кола", която не съществува в реалността. Същият пример може да се даде и с животните. Представете си, ако вашата програма има Animalобекти (" само животни "). Не е ясно Howъв вид е, към Howво семейство принадлежи or Howви характеристики има. Би било странно да видите такъв в програма. В природата няма "само животни". Само кучета, котки, лисици, къртици и т.н. Абстрактните класове ни спасяват от " просто обекти ". Те ни дават базово състояние и поведение. Например, всички автомобor трябва да имат модел , цвят и максимална скорост, и те също трябва да могат да подават газ и спирачка . Това е. Това е общ абстрактен план, който ще използвате по-късно, за да проектирате класовете, от които се нуждаете. Забележка: двата метода в абстрактния клас също са абстрактни , което означава, че нямат ниHowва реализация. Причината е същата: абстрактните класове не създават "поведения по подразбиране" за "само автомобor". Те просто показват Howво трябва да може да прави всяка кола. Въпреки това, ако имате нужда от поведение по подразбиране, можете да имплементирате методи в абстрактен клас. Java не забранява това:

public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       System.out.println("Accelerating!");
   }

   public abstract void brake();
  
   // Getters and setters
}


public class Sedan extends Car {

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }

}

public class Main {

   public static void main(String[] args) {

       Sedan sedan = new Sedan();
       sedan.gas();
   }
}
Изход от конзолата:
Accelerating!
Както можете да видите, внедрихме един метод в абстрактния клас, но не и другия. В резултат на това поведението на нашия Sedanклас е разделено на две части: ако извикаме неговия gas()метод, поведението се „изтегля“ от абстрактния Carродителски клас и ние имплементираме brake()метода в Sedanкласа. Това е супер удобно и гъвкаво. Но нашият клас вече не е толкова абстрактен, нали ? В края на краищата той реално внедри половината от методите. Факт е - и това е много важна характеристика - един клас е абстрактен, ако дори един от неговите методи е абстрактен. Един метод от два or един от хиляда - няма meaning. Можем дори да приложим всички методи, без да оставим нито един абстрактен. Резултатът би бил абстрактен клас без ниHowви абстрактни методи. По принцип това е възможно — компилаторът няма да генерира ниHowви грешки — но е по-добре да не го правите, тъй като това лишава думата абстрактно от нейното meaning. Вашите колеги програмисти също ще бъдат много изненадани да видят това :/ Въпреки това, ако даден метод е маркиран като абстрактен, всеки клас наследник трябва да го имплементира or да бъде деклариран като абстрактен. В противен случай компилаторът ще изведе грешка. Разбира се, всеки клас може да наследи само един абстрактен клас, така че няма разлика между абстрактните и обикновените класове по отношение на наследяването. Няма meaning дали наследяваме абстрактен клас or обикновен — може да има само един родителски клас.

Защо Java няма множествено наследяване на класове

Вече казахме, че в Java няма множествено наследяване, но не се задълбочихме защо. Нека се опитаме да направим това сега. Факт е, че ако Java имаше множествено наследяване, тогава дъщерните класове нямаше да могат да решат кое поведение да изберат. Да кажем, че имаме два класа: Toasterи NuclearBomb:

public class Toaster {
  
  
 public void on() {

       System.out.println("The toaster is on. We're toasting!");
   }
  
   public void off() {

       System.out.println("The toaster is off!");
   }
}


public class NuclearBomb {

   public void on() {

       System.out.println("Boom!");
   }
}
Както можете да видите, и двата класа имат on()метод. За тостера методът започва да прави препечен хляб, но в случая с ядрената бомба предизвиква експлозия. О-о :/ Сега си представете, че сте решor (не ме питайте защо!) да създадете нещо между тях. Ето вашия клас: MysteriousDevice! Този code няма да работи, разбира се. Представяме го просто като пример за "Howво може да е било":

public class MysteriousDevice extends Toster, NuclearBomb {

   public static void main(String[] args) {
      
       MysteriousDevice mysteriousDevice = new MysteriousDevice();
       mysteriousDevice.on(); // And what should happen here? Will we get toast or a nuclear apocalypse?
   }
}
Да видим Howво имаме. Мистериозното устройство произлиза едновременно от Toaster и NuclearBomb. И двете имат on()метод. В резултат на това не е ясно кое изпълнение трябва да се изпълни, ако извикаме on()обект MysteriousDevice. Обектът няма да разбере. И като капак на всичко, NuclearBomb няма off()метод, така че ако не познаем правилно, тогава ще бъде невъзможно да изключим устройството. Конкретни примери за абстрактни класове в Java - 2Това "недоразумение", когато не е ясно кое поведение трябва да се изпълни, е точно причината, поради която създателите на Java отхвърлиха множественото наследяване. Въпреки това ще научите, че Java класовете могат да реализират много интерфейси.