类、继承和重写
前言
现实生活中,对象就是事物存在的实体。对象又可以分为静态部分和动态部分。静态部分,顾名思义就是不能动(保持不变)的部分,这一部分被称之为“属性”,任何对象都具有自身属性。而动态部分就是指具有静态属性的对象执行的各种行为。在Java中,这些行为就称之为方法。所以,对生活中事物的特征进行抽象概括,对其属性和行为进行封装,就能创建出对象。
一、类
类就是同一类事物的统称。
本质上,类就是封装对象属性和行为的载体。
类是抽象事物的全体,而对象是类中事物的实体,每一个对象都有所属的类。
宽泛地讲,类中的方法是类的应用程序接口,定义着用户和实例之间的作用。
1. 成员变量
在Java语言中对象的属性也称为成员变量。成员变量其实就是普通的变量,可以设置初始值,也可以不设置初始值。如果不设置初始值,则会有系统默认值。
2. 成员方法
在Java语言中使用成员方法对应于类对象的行为。一个成员方法可以有或者没有参数,这个参数可以是对象,也可以是基本数据类型的变量。成员也可以有或者没有返回值。
3. 权限修饰符
Java中的权限修饰符主要包括private public和protected,这些修饰符控制着对类和类的成员变量以及成员方法的访问。在设置权限修饰符时,一般讲提供给用户的变量和方法设置为public,而将其他的设置为privated或者protected。
访问包位置 | private | public | protected |
---|---|---|---|
声明所在的类 | 可见 | 可见 | 可见 |
同包下的其他类或子类 | 不可见 | 可见 | 可见 |
其他包下的类或子类 | 不可见 | 可见 | 不可见 |
4. 代码示例
代码如下(示例):
public class Car {
/* 定义Car的属性——成员变量 */
private final int price; //车价
private final int width; //车宽
public String driver; //驾驶员
public String brand; //品牌
//public类型,属于构造器
public Car(int price, int width, String driver, String brand) {
this.price= price;
this.width = width;
this.driver = driver;
this.brand= brand;
}
/* public类型——成员方法 */
//返回车价
public String getPrice() {
return price;
}
//返回车宽
public int getWidth() {
return width;
}
//返回驾驶员
public String getDriver() {
return driver;
}
//返回车的品牌
public String getBrand() {
return brand;
}
}
二、继承和重写
1. 继承
在Java语言中,类的继承是指在一个现有类的基础上去构建一个新的类。构建出来的新类被称作子类,现有类被称作父类,子类会自动拥有父类所有可继承的属性和方法。在Java程序中,如果想声明一个类继承另一个类,需要使用extends关键字。
(1)继承的特点
- 一个类只能继承于某一个类,不能继承于多个类
- 多个类可以继承于同一个类
- 类的继承可以传递继承,意思就是可以出现“祖孙”类
- 一个类既可以继承其他类,也可以被其他类继承,也就是说一个类,既可以是父类的身份,也可以是子类的身份
(2)继承示例
沿用上述构造的Car类型,代码如下(示例):
1) 多个类可以继承于同一个类
子类型HongQi继承Car类
public class HongQi extends Car {
@override
public String getBrand() {
Car HongQi_new = new Car(300000, 3, "Jack", "HongQi");
//此处应重写equals, Hashcode方法
if(!this.brand.equals(HongQi_new)){
System.out.printlt("Your band is wrong!");
System.exit(0);
}
return brand;
}
}
子类型Geely继承Car类
public class Geely extends Car {
@override
public String getBrand() {
Car Geely_DH = new Car(100000, 3, "Ball", "Geely");
//此处应重写equals, Hashcode方法
if(!this.brand.equals(Geely_DH)){
System.out.printlt("Your band is wrong!");
System.exit(0);
}
return brand;
}
}
2 ) 类的继承可以传递继承
红旗汽车中的红旗H9系列属于红旗汽车,所以HongQi_H9是HongQi的继承
public class HongQi_H9 extends HongQi {
@override
public String getBrand() {
Car HongQi_H9 = new Car(539800, 3, "HUA", "HongQi");
//此处应重写equals, Hashcode方法
if(!this.brand.equals(HongQi_H9)){
System.out.printlt("Your band is wrong!");
System.exit(0);
}
return brand;
}
}
3 ) 一个类既可以继承其他类,也可以被其他类继承
由上述例子可知,HongQi类继承于Car类,HongQi_H9类又继承于HongQi类
2. 重写
重写是子类对父类方法进行改写。实际执行时调用哪个方法,由运行时决定。
重写之后,复用了父类型中函数的功能,并能对其进行扩展。
(1) 重写的要求
- 如果返回值是void类型或者基本数据类型,确保子类中重写的方法和父类中被重写的方法具有相同的方法名、参数列表以及返回值类型,可以使用@override可以让编译器检查覆盖方法和被覆盖的方法签名是否完全一致。
- 如果返回值是引用数据类型,则子类重写方法的返回值类型需要和父类被重写方法的返回值类型保持一致或是其子类
- 对某些子类型来说,可能有不同于父类型的特殊需求,故重写父类型中的函数,实现自己的特殊需求。但覆盖时,子类方法的权限一定要大于等于父类方法的权限。
- 父类中的私有方法不可以被覆盖,static的方法无法覆盖。
- 父类型中的被重写函数体不可以为空,意味着对于大多数子类型来说,该方法是可以被直接复用的。如果父类型中的某个函数实现体为空,意味着其所有子类型都需要这个功能,但各有差异,没有共性,在每个子类中均需要重写。
(2) 重写的示例
重写equals, Hashcode方法,代码如下(示例):
@Override
public boolean equals(Object car) {
if (!(HongQi instanceof Car))
return false;
else{
HongQi that = (HongQi car;
return (that.brand == this.brand) && (that.width== this.width);
}
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + brand.hashCode();
result = 31 * result + width.hashCode();
return result;
}
总结
本文介绍了类、继承和重写的相关知识,水平有限,如有纰漏,敬请指正。