你好!在前面的讲座中,我们已经多次简单地遇到过继承的概念。今天我们也会触及这个话题,但也不会太深入。稍后会有详细的讲座,但今天我们只看实际示例并熟悉 Java 中的一个有趣的运算符。
Java继承
那么,继承到底是什么? 继承是编程(包括 Java)中的一种机制,它允许您基于现有类来描述新类。然后,后代类可以访问父类的字段和方法。为什么这是必要的?举例来说,假设您需要在程序中创建几种类型的汽车:卡车、赛车、轿车、皮卡等。即使不开始编写代码,您也可以确定这些类有很多共同点:所有汽车都有型号名称、制造年份、发动机尺寸、最高速度等。(更不用说它们都有轮子和其他零件)。在这种情况下,您可以:- 在每个类中创建这些字段,并在创建时将它们添加到新的汽车类中
- 将所有机器共有的字段移到父类中
Car
,特定类型机器的所有类都使用extendsCar
一词继承。
public class Car {
private String model;
private int maxSpeed;
private int yearOfManufacture;
public Car(String model, int maxSpeed, int yearOfManufacture) {
this.model = model;
this.maxSpeed = maxSpeed;
this.yearOfManufacture = yearOfManufacture;
}
}
public class Truck extends Car {
public Truck(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
public class Sedan extends Car {
public Sedan(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
至少,我们避免了不必要的代码重复,这是我们在编写程序时应该始终努力做到的。此外,我们还有一个简单易懂的类结构:所有机器共有的字段都放在一个类中。例如,如果卡车具有其他汽车没有的某些特定字段,则可以在类中声明它们Truck
。方法也是如此。所有汽车都有一些可以描述的共同行为:启动汽车、油门/刹车等。这些通用方法可以放在一个通用类中Car
,而每个特定类型的具体行为可以在后代类中描述。
public class Car {
public void gas() {
//...gas
}
public void brake() {
//...brake
}
}
public class F1Car extends Car {
public void pitStop() {
//...only racing cars make pit stops
}
public static void main(String[] args) {
F1Car formula1Car = new F1Car();
formula1Car.gas();
formula1Car.pitStop();
formula1Car.brake();
}
}
我们已经将所有汽车的通用方法移到了类中Car
。但在后继类别中F1Car
,描述了一级方程式赛车 - 进站(紧急维修汽车时的停车),仅在比赛中进行,并通过特定行为进行区分。
Java实例化运算符
要检查一个对象是否是基于类创建的,Java中有一个特殊的运算符 -instanceof
。true
如果测试为真,则返回该值,或者false
如果结果为假,则返回该值。让我们以我们的汽车类为例看看它是如何工作的:
public class Truck extends Car {
public static void main(String[] args) {
Truck truck = new Truck();
System.out.println(truck instanceof Car);
}
}
输出: true 使用运算符进行的检查instanceof
返回true
,因为我们有 类的对象Truck
,并且所有卡车都是汽车。该类Truck
是该类的后代Car
,因此,所有卡车都是基于共同的父级(汽车)创建的。注意运算符instanceof
:它没有点,因为它是一个运算符,而不是一个方法(“object instanceof Class”)。让我们尝试一下不同的方法:
public static void main(String[] args) {
Car car = new Car();
System.out.println(car instanceof Truck);
}
输出: false 该类Car
及其对象并非派生自该类。Truck
所有卡车都是汽车,但并非所有汽车都是卡车。对象Car
不是基于类创建的Truck
。再举一个例子:
public static void main(String[] args) {
Car car = new Car();
Truck truck = new Truck();
System.out.println(car instanceof Object && truck instanceof Object);
}
输出: True 这里的逻辑也很简单:Java 中的所有类,包括您创建的类,都来自一个类Object
(尽管您没有在其中编写extends Object - 这种机制是隐式的)。为什么这可能有用以及在什么情况下有用?运算符最常见的用途instanceof
是作为方法重写equals()
。例如,以下是该方法equals
在类中的实现方式String
:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
在将字符串与传递的对象进行比较之前,该方法会检查:传递的对象实际上是字符串吗?只有那时他才开始比较两个物体的属性。如果没有此检查,您可以将任何具有值和长度字段的对象传递到该方法中并将其与字符串进行比较,这当然是错误的。
GO TO FULL VERSION