【JAVA 笔记】06 车辆属性抽象类
要求
写出一个抽象类Car,具有Brand、PowerMode、MaxSpeed、Price四个保护属性,分别为String、String、整型和双精度浮点型,且具有公有的getPrice和getPowerMode方法(用于返回Price和PowerMode变量的值)和一个无参的抽象方法Start;以Car类为父类派生出一个子类NEV,NEV类具有属性NEDC(续航里程,为整型),且实现无参Start方法,功能是在屏幕上输出字符串:走起!然后再设计一个测试类(CarTest.java),在main方法中创建一个NEDC为800公里、Brand为BYD、PowerMode为PHEV、MaxSpeed为220公里、Price为36万NEV类的对象Whale,并执行它的Start方法。
下面是一个包含抽象类 Car
和其子类 NEV
的 Java 示例代码,以及一个测试类 CarTest
来验证这些类的功能。
抽象类 Car
首先定义一个抽象类 Car
,它包含四个受保护的属性,并提供公共的 getPrice
和 getPowerMode
方法。同时定义了一个抽象方法 Start
。
public abstract class Car {
protected String brand; // 品牌
protected String powerMode; // 动力模式
protected int maxSpeed; // 最高速度
protected double price; // 价格
public Car(String brand, String powerMode, int maxSpeed, double price) {
this.brand = brand;
this.powerMode = powerMode;
this.maxSpeed = maxSpeed;
this.price = price;
}
public double getPrice() {
return price;
}
public String getPowerMode() {
return powerMode;
}
// 抽象方法,由子类实现
public abstract void Start();
}
子类 NEV
接下来定义一个继承自 Car
的子类 NEV
,增加一个 nedc
属性表示续航里程,并实现 Start
方法。
public class NEV extends Car {
private int nedc; // 续航里程
public NEV(String brand, String powerMode, int maxSpeed, double price, int nedc) {
super(brand, powerMode, maxSpeed, price);
this.nedc = nedc;
}
// 实现抽象方法
@Override
public void Start() {
System.out.println("走起!");
}
public int getNEDC() {
return nedc;
}
}
测试类 CarTest
最后编写一个测试类 CarTest
,在 main
方法中创建一个 NEV
类的对象,并调用它的 Start
方法。
public class CarTest {
public static void main(String[] args) {
// 创建一个NEV对象
NEV whale = new NEV("BYD", "PHEV", 220, 360000, 800);
// 调用Start方法
whale.Start();
}
}
说明
-
抽象类 Car:
- 定义了品牌、动力模式、最高速度和价格四个属性。
- 提供了获取价格和动力模式的公共方法。
- 定义了一个抽象方法
Start
,需要子类实现。
-
子类 NEV:
- 继承自
Car
类。 - 增加了一个续航里程
nedc
属性。 - 实现了
Start
方法,输出“走起!”。
- 继承自
-
测试类 CarTest:
- 创建了一个
NEV
类的对象,并设置了相应的属性。 - 调用了
Start
方法来测试是否正确输出。
- 创建了一个
这样就完成了一个简单的汽车类的定义及其测试。在这个例子中,NEV
是一个新能源车,通过 Start
方法模拟启动车辆的行为。
好的,我们来详细分析一下如何设计这个程序,包括抽象类 Car
、派生类 NEV
和测试类 CarTest
。
设计思路
1. 抽象类 Car 的设计
- 目的:定义所有类型汽车共有的属性和行为。
- 属性:品牌 (
brand
)、动力模式 (powerMode
)、最高速度 (maxSpeed
) 和价格 (price
)。 - 方法:
getPrice()
:返回汽车的价格。getPowerMode()
:返回汽车的动力模式。Start()
:抽象方法,由子类具体实现,用于模拟汽车启动的行为。
2. 子类 NEV 的设计
- 目的:定义新能源汽车特有的属性和行为。
- 新增属性:续航里程 (
nedc
)。 - 方法:实现父类
Car
中定义的抽象方法Start()
,用于模拟新能源汽车启动的行为。
3. 测试类 CarTest 的设计
- 目的:测试
NEV
类的功能。 - 行为:创建一个
NEV
类的实例,并调用其Start()
方法。
代码实现
1. 抽象类 Car
public abstract class Car {
// 受保护的属性,可以被子类访问
protected String brand; // 品牌
protected String powerMode; // 动力模式
protected int maxSpeed; // 最高速度
protected double price; // 价格
// 构造函数
public Car(String brand, String powerMode, int maxSpeed, double price) {
this.brand = brand;
this.powerMode = powerMode;
this.maxSpeed = maxSpeed;
this.price = price;
}
// 获取价格
public double getPrice() {
return price;
}
// 获取动力模式
public String getPowerMode() {
return powerMode;
}
// 抽象方法,由子类实现
public abstract void Start();
}
2. 子类 NEV
public class NEV extends Car {
// 新增属性,续航里程
private int nedc;
// 构造函数
public NEV(String brand, String powerMode, int maxSpeed, double price, int nedc) {
super(brand, powerMode, maxSpeed, price);
this.nedc = nedc;
}
// 获取续航里程
public int getNEDC() {
return nedc;
}
// 实现抽象方法 Start
@Override
public void Start() {
System.out.println("走起!");
}
}
3. 测试类 CarTest
public class CarTest {
public static void main(String[] args) {
// 创建一个NEV对象
NEV whale = new NEV("BYD", "PHEV", 220, 360000, 800);
// 输出车辆信息
System.out.println("品牌:" + whale.brand);
System.out.println("动力模式:" + whale.getPowerMode());
System.out.println("最高速度:" + whale.maxSpeed + "公里");
System.out.println("价格:" + whale.getPrice() + "万元");
System.out.println("续航里程:" + whale.getNEDC() + "公里");
// 调用Start方法
whale.Start();
}
}
解释
-
抽象类 Car:
- 定义了四个受保护的属性:
brand
,powerMode
,maxSpeed
,price
。 - 提供了一个构造函数,用于初始化这些属性。
- 提供了两个公共方法
getPrice()
和getPowerMode()
用于获取价格和动力模式。 - 定义了一个抽象方法
Start()
,由子类具体实现。
- 定义了四个受保护的属性:
-
子类 NEV:
- 继承自
Car
类。 - 添加了一个私有属性
nedc
表示续航里程。 - 提供了一个构造函数,用于初始化父类和自身的新属性。
- 实现了
Start()
方法,输出 “走起!” 表示汽车启动。
- 继承自
-
测试类 CarTest:
- 在
main
方法中创建了一个NEV
类的对象whale
。 - 输出了对象的一些基本信息。
- 调用了
Start()
方法来模拟汽车启动。
- 在
这样我们就完成了整个程序的设计与实现。通过这种方式,我们可以很容易地扩展其他类型的汽车,只需要继承 Car
类并实现 Start()
方法即可。
完整运行代码整理
抽象类 Car
public abstract class Car {
// 受保护的属性,可以被子类访问
protected String brand; // 品牌
protected String powerMode; // 动力模式
protected int maxSpeed; // 最高速度
protected double price; // 价格
// 构造函数
public Car(String brand, String powerMode, int maxSpeed, double price) {
this.brand = brand;
this.powerMode = powerMode;
this.maxSpeed = maxSpeed;
this.price = price;
}
// 获取价格
public double getPrice() {
return price;
}
// 获取动力模式
public String getPowerMode() {
return powerMode;
}
// 抽象方法,由子类实现
public abstract void Start();
}
子类 NEV
public class NEV extends Car {
// 新增属性,续航里程
private int nedc;
// 构造函数
public NEV(String brand, String powerMode, int maxSpeed, double price, int nedc) {
super(brand, powerMode, maxSpeed, price);
this.nedc = nedc;
}
// 获取续航里程
public int getNEDC() {
return nedc;
}
// 实现抽象方法 Start
@Override
public void Start() {
System.out.println("走起!");
}
}
测试类 CarTest
public class CarTest {
public static void main(String[] args) {
// 创建一个NEV对象
NEV whale = new NEV("BYD", "PHEV", 220, 360000, 800);
// 输出车辆信息
System.out.println("品牌:" + whale.brand);
System.out.println("动力模式:" + whale.getPowerMode());
System.out.println("最高速度:" + whale.maxSpeed + "公里");
System.out.println("价格:" + whale.getPrice() + "万元");
System.out.println("续航里程:" + whale.getNEDC() + "公里");
// 调用Start方法
whale.Start();
}
}
说明
-
抽象类 Car:
- 定义了四个受保护的属性:
brand
,powerMode
,maxSpeed
,price
。 - 提供了一个构造函数,用于初始化这些属性。
- 提供了两个公共方法
getPrice()
和getPowerMode()
用于获取价格和动力模式。 - 定义了一个抽象方法
Start()
,由子类具体实现。
- 定义了四个受保护的属性:
-
子类 NEV:
- 继承自
Car
类。 - 添加了一个私有属性
nedc
表示续航里程。 - 提供了一个构造函数,用于初始化父类和自身的新属性。
- 实现了
Start()
方法,输出 “走起!” 表示汽车启动。
- 继承自
-
测试类 CarTest:
- 在
main
方法中创建了一个NEV
类的对象whale
。 - 输出了对象的一些基本信息。
- 调用了
Start()
方法来模拟汽车启动。
- 在
编译和运行
为了编译和运行上述代码,你需要将它们保存在三个不同的文件中:
Car.java
文件中包含Car
类。NEV.java
文件中包含NEV
类。CarTest.java
文件中包含CarTest
类。
然后,可以在命令行中使用以下命令编译这些类:
javac Car.java NEV.java CarTest.java
编译完成后,可以使用以下命令运行 CarTest
类:
java CarTest
运行结果应该如下所示:
品牌:BYD
动力模式:PHEV
最高速度:220公里
价格:360000.0万元
续航里程:800公里
走起!
好的,我们将进一步拓展这篇文章的内容,深入探讨面向对象编程(OOP)的核心概念,并结合具体代码示例进行详细解释。
面向对象编程的核心概念
1. 封装(Encapsulation)
封装是面向对象编程的一个基本特性,它指的是将数据和操作数据的方法捆绑在一起,形成一个整体(即对象)。封装还包括隐藏内部状态和实现细节,只暴露必要的接口给外部使用。
在代码示例中,Car
类的属性都是受保护的(protected
),这意味着它们只能被类本身及其子类访问。而 getPrice()
和 getPowerMode()
方法则提供了访问这些属性的方式,这是封装的一个典型应用。
2. 继承(Inheritance)
继承允许一个类继承另一个类的属性和方法。继承使得代码复用成为可能,并且可以建立类之间的层次关系。
在本例中,NEV
类继承了 Car
类,因此它自动获得了 Car
类的所有非私有属性和方法。此外,NEV
类还可以定义自己的新属性和方法,如 nedc
和 getNEDC()
方法。
3. 多态(Polymorphism)
多态是指允许不同类的对象对同一消息作出响应的能力。简单来说,就是“一种接口,多种实现”。在 Java 中,多态可以通过方法覆盖(overriding)和方法重载(overloading)来实现。
在代码示例中,Car
类定义了一个抽象方法 Start()
,而 NEV
类实现了这个方法。这意味着虽然 Start()
方法在 Car
类中是抽象的,但在 NEV
类中它有了具体的实现。这就是多态的一种体现。
更深入的技术细节
1. 抽象类与接口的区别
尽管在前面的示例中我们使用了抽象类,但在某些情况下,接口可能是更好的选择。接口与抽象类的区别在于:
- 抽象类 可以包含具体实现的方法,而接口只能包含抽象方法。
- 接口 支持多重继承,而 Java 中的类只能继承单一的抽象类。
- 抽象类 可以拥有构造函数,而接口不可以。
在实际应用中,如果需要强制多个类遵守相同的协议,而不关心它们的实现细节,那么接口是一个更好的选择。
2. 构造函数与初始化
在 NEV
类中,我们定义了一个构造函数来初始化父类的属性和自身的属性。构造函数是对象创建时被自动调用的方法,用于设置初始状态。
public NEV(String brand, String powerMode, int maxSpeed, double price, int nedc) {
super(brand, powerMode, maxSpeed, price); // 调用父类构造器
this.nedc = nedc;
}
这里 super
关键字用于调用父类的构造函数,确保父类的属性被正确初始化。
3. 方法覆盖与方法重载
- 方法覆盖(Overriding) 发生在子类中,子类重写了父类的方法,以提供具体的实现。在我们的例子中,
NEV
类覆盖了Car
类的Start()
方法。
@Override
public void Start() {
System.out.println("走起!");
}
- 方法重载(Overloading) 则是指在同一类中定义多个同名方法,但参数列表不同。这在当前示例中没有体现,但在实际开发中非常常见。
4. 访问修饰符的作用
在 Java 中,有四种访问修饰符:public
、protected
、private
和默认(无修饰符,也称为包级访问)。这些修饰符决定了类、方法或属性的可见性范围。
public
:在任何地方都可以访问。protected
:只有在同一包内或者子类可以访问。private
:只有在定义它的类内部可以访问。- 默认:只有在同一包内可以访问。
在 Car
类中,我们使用了 protected
修饰符来保护属性不被外部直接访问。
实际应用中的考虑
1. 异常处理
在实际应用中,你可能需要处理各种异常情况,比如输入非法的数据。可以通过抛出异常或进行条件检查来保证代码的健壮性。
2. 日志记录
对于复杂的系统,记录日志可以帮助跟踪程序的状态和调试问题。例如,可以在 Start()
方法中添加日志记录:
public void Start() {
System.out.println("走起!");
// 记录日志
System.out.println("NEV " + getBrand() + " 已经启动.");
}
3. 国际化与本地化
如果应用程序需要支持多种语言和地区,那么就需要考虑如何在不同的环境中正确地显示信息。例如,可以使用资源文件来管理不同的语言文本。