CodeGym/Java 博客/随机的/Java中抽象类的具体例子
John Squirrels
第 41 级
San Francisco

Java中抽象类的具体例子

已在 随机的 群组中发布
个会员
你好!在过去的课程中,我们遇到了接口并弄清楚了它们的用途。今天的话题与之前的话题相呼应。让我们谈谈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;
   }
}
这就是最简单的抽象类的样子。如您所见,它没什么特别的:) 为什么我们需要它?首先,它以最抽象的方式描述了我们所需的实体,即汽车。我们使用抽象这个词是有原因的。在现实世界中,没有“抽象汽车”。有卡车、赛车、轿车、轿跑车和 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 gas() {
       // Some logic
   }

    public void brake() {
       // Some logic
   }
}


public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Everything is fine. A car is created.
   }
}
现在我们的程序有某种难以理解的汽车——它不是卡车,不是赛车,也不是轿车,而且完全不清楚它是什么。这是自然界中不存在的非常“抽象的汽车”。我们可以使用动物提供相同的示例。想象一下如果Animal类(抽象动物)。目前还不清楚它是什么动物,属于什么科,有什么特征。在您的程序中看到这一点会很奇怪。自然界中没有“抽象动物”。只有狗、猫、狐狸、鼹鼠等。抽象类将我们从抽象对象中解放出来。它们为我们提供了基本的状态和行为。例如,所有汽车都应该有modelcolormaximum speed,你应该能够应用油门刹车。就是这样。这是一个通用的抽象计划。接下来你设计你需要的类。 注意:抽象类中的两个方法也被指定为abstract,它们没有任何实现。原因是一样的:抽象类不会为抽象汽车创建默认行为。它们只是表明每辆车应该能够做什么。但是,如果确实需要默认行为,则可以在抽象类中实现方法。Java 不禁止这样做:
public abstract class Car {

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

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

   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();
   }
}
控制台输出: “Gas!” 如您所见,我们在抽象类中实现了第一个方法,而不是第二个方法。因此,我们Sedan类的行为分为两部分:如果调用该gas()方法,则调用'上升'到Car抽象父类,但是我们覆盖了类brake()中的方法Sedan。这样非常方便和灵活。但是现在我们的类不那么抽象了?毕竟它的方法实现了一半。这个实际上是一个非常重要的特性——如果至少有一个方法是抽象的,那么这个类就是抽象的. 两种方法中的一种,或至少一千种方法中的一种——都没有区别。我们甚至可以实现所有的方法,并且不保留任何抽象方法。那么它就是一个没有抽象方法的抽象类。原则上,这是可能的,编译器不会产生错误,但最好避免它:抽象这个词失去了意义,你的程序员同行们会很惊讶:/ 同时,如果一个方法被标记使用抽象一词,每个子类都必须实现它或将其声明为抽象。否则,编译器将产生错误。 当然,每个类只能继承一个抽象类,所以抽象类和普通类在继承上没有区别。不管我们继承抽象类还是普通类,都只能有一个父类。

为什么Java没有类的多重继承

我们已经说过 Java 没有多重继承,但我们还没有真正探究为什么。让我们现在尝试这样做。事实上,如果 Java 具有多重继承,子类将无法决定它们应该选择哪种特定行为。假设我们有两个类——ToasterNuclearBomb
public class Toaster {


 public void on() {

       System.out.println("The toaster is on. Toast is being prepared!");
   }

   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 Toaster, NuclearBomb {

   public static void main(String[] args) {

       MysteriousDevice mysteriousDevice = new MysteriousDevice();
       mysteriousDevice.on(); // So what should happen here? Do we get toast or a nuclear apocalypse?
   }
}
让我们来看看我们有什么。这个神秘装置同时继承了 Toaster 和 NuclearBomb。两者都有on()方法。因此,如果我们调用该on()方法,则不清楚应该在MysteriousDevice对象上调用哪个方法。对象不可能知道。最重要的是:NuclearBomb 没有off()方法,所以如果我们没有猜对,就不可能禁用该设备。 Java中抽象类的具体例子——2正是由于这种“混乱”,对象不知道该表现出什么行为,Java 的创建者才放弃了多重继承。但是,您会记得 Java 类可以实现多个接口。 顺便说一句,在您的学习中,您已经至少遇到过一个抽象类!
public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar>
这是你的老朋友,班级Calendar。它是抽象的,有几个孩子。其中之一是GregorianCalendar。您已经在有关日期的课程中使用过它。:) 一切似乎都很清楚。只有一个问题:抽象类和接口之间的根本区别到底是什么?为什么他们将两者都添加到 Java 而不是将语言限制为一种?毕竟,那已经完全足够了。我们将在下一课讨论这个!直到那时 :)
评论
  • 受欢迎
你必须先登录才能发表评论
此页面还没有任何评论