你好!让我们谈谈Java中的抽象类Java抽象类的具体例子——1

为什么类被称为“抽象”?

您可能还记得抽象是什么——我们之前讨论过 :) 如果您忘记了,不用担心。请记住, OOP 原则说,在设计类和创建对象时,您应该只表示实体的主要属性并丢弃次要属性。例如,如果我们正在设计一个SchoolTeacher班级,身高可能不是教师的必要属性。事实上,这个特征对于老师来说并不重要。但是如果我们要创建一个BasketballPlayer类,那么高度将是最重要的特征之一。好吧,一个抽象类是一组未来类的最抽象、“粗糙的工件”。工件不能直接使用——太“粗糙”了。但它定义了未来类(抽象类的后代)将具有的某些特征状态和行为。

Java中抽象类的例子

考虑一个简单的汽车示例:

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;
   }
}
这就是最简单的抽象类的样子。如您所见,没什么特别的:) 为什么我们需要这个?首先,它提供了我们所需实体的最抽象描述——汽车。abstract关键字在这里意味着什么。在现实世界中,没有“只是一辆车”这样的东西。有卡车、赛车、轿车、轿跑车和 SUV。我们的抽象类只是一个“蓝图”,我们稍后将使用它来创建特定的汽车类。

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.
   }
}
目前,我们的程序中有某种无法理解的汽车。它不是卡车,不是赛车,也不是轿车,但并不清楚它是什么。是现实中不存在的“只是一辆车”。同样的例子也可以用在动物身上。想象一下,如果您的程序有Animal对象(“只是动物”)。目前尚不清楚它是什么种类,属于哪个家族,或者具有什么特征。在节目中看到一个会很奇怪。自然界中没有“只是动物”。只有狗、猫、狐狸、鼹鼠等。抽象类将我们从“只是对象”中拯救出来。它们为我们提供了基准状态和行为。例如,所有汽车都必须有型号颜色最高时速,而且他们还必须能够使用油门刹车。就是这样。这是一个通用的抽象蓝图,您稍后将使用它来设计您需要的类。注意:抽象类中的两个方法也是抽象的,也就是说它们根本没有实现。原因是一样的:抽象类不会为“只是汽车”创建“默认行为”。它们只是表明每辆车必须能够做什么。也就是说,如果您确实需要默认行为,则可以在抽象类中实现方法。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类中实现方法。这是超级方便和灵活的。但是我们的类现在不那么抽象了,是吗?毕竟,它实际上实现了一半的方法。事实是——这是一个非常重要的特征——即使一个类的方法是抽象的,它也是抽象的. 两种方法中的一种,或千种方法中的一种——都没关系。我们甚至可以实现所有方法,不留下任何抽象。结果将是一个没有任何抽象方法的抽象类。原则上这是可能的——编译器不会产生任何错误——但最好不要这样做,因为它剥夺了抽象这个词的意义。你的程序员伙伴看到这个也会很惊讶:/也就是说,如果一个方法被标记为抽象的,每个后代类都必须实现它或被声明为抽象的。否则编译器会报错. 当然,每个类只能继承一个抽象类,所以抽象类和普通类在继承上没有区别。我们继承抽象类还是普通类并不重要——父类只能有一个。

为什么Java没有多类继承

我们已经说过 Java 中没有多重继承,但我们并没有真正深究为什么。让我们现在尝试这样做。事实上,如果 Java 确实具有多重继承,那么子类将无法决定选择哪种行为。假设我们有两个类:ToasterNuclearBomb

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()方法。对于烤面包机,该方法开始烤面包,但对于核弹,它会引发爆炸。呃哦:/现在想象一下你已经决定(不要问我为什么!)在两者之间创造一些东西。这是你的课MysteriousDevice:当然,这段代码是行不通的。我们仅将其作为“可能发生的情况”的示例进行介绍:

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?
   }
}
让我们看看我们有什么。这个神秘装置同时源自烤面包机和核弹。两者都有一个on()方法。on()因此,如果我们调用一个对象,则不清楚应该执行哪个实现MysteriousDevice。对象不会理解。最重要的是,NuclearBomb 没有off()方法,所以如果我们没有猜对,就不可能关闭设备。Java抽象类的具体例子-2这种“误解”,在不清楚应该执行哪个行为时,正是 Java 的创造者拒绝多重继承的原因。也就是说,您将了解到 Java 类可以实现许多接口。