1.什么是继承?
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
举个例子:
兔子和羊属于食草动物类,狮子和豹属于食肉动物类。
食草动物和食肉动物又是属于动物类。
所以继承需要符合的关系是:is-a,父类更通用,子类更具体。
虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。
2.类的继承格式
在JAVA中通常采用 extends 关键字使一个类继承另一个类,具体如下
class 父类 {
}
class 子类 extends 父类 {
}
具体实现
开发需求:开发学生类,其中的学生分别为小明和小红
——小明:属性(姓名,年龄),方法(自我介绍)
——小红:属性(姓名,年龄,成绩),方法(自我介绍,考试)
//小明类
public class Ming {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void introduce() {
System.out.println("My name is "+getName()+",I am "+getAge()+" years old.");
}
}
//小红类
public class Hong {
private int age;
private String name;
private int score;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int age) {
this.score = score;
}
public void introduce() {
System.out.println("My name is "+getName()+",I am "+getAge()+" years old.");
}
public void test() {
System.out.println("Your grades are"+getScore());
}
}
从这两段代码可以看出来,代码存在大量重复,导致后果就是代码量大且臃肿,我们编写起来很麻烦,而且维护性不高(维护性主要是后期需要修改的时候,就需要修改很多的代码,容易出错),,所以要从根本上解决这两段代码的问题,就需要继承,比如小红的部分属性和方法就可以继承小明的:
//继承了小明的属性(姓名,年龄),和方法(自我介绍),并且可以添加属于自己的属性和方法
public class Hong extends Ming {
private int score;
public int getScore() {
return score;
}
public void setScore(int age) {
this.score = score;
}
public void test() {
System.out.println("Your grades are"+getScore());
}
}
被继承的类(Person)称为父类,也叫超类,实现继承的类(Student)叫子类,也称派生类。 通过继承Student类拥有了父类的属性和方法,简化了代码。
//完成 main 方法
public static void main(String[] args) {
Hong hong=new Hong();
hong.setAge(18);
hong.setName("小红");
hong.introduce();
}
//运行结果
My name is 小红,I am 18 years old.
继承类型
继承类型
Java 不支持多继承,但支持多重继承
继承特性
1.子类拥有父类非private的属性,方法
如果把上面Ming类的introduce方法改为private,Hong类对象不能引用。
2.子类可以拥有自己的属性和方法,即子类可以对父类进行扩展(可以理解为:“子类 is a 父类” )
上面例子中,Hong类除了继承Ming类的属性和方法,还拥有score属性和test方法.
3.子类可以重写父类的方法
重写定义:在子类中可以根据需要对从父类中继承来的方法进行改造,也称方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。
在上面的例子中,Hong类继承了Ming类的方法,我们可以在Hong类中对Ming类的introduce方法进行重写
//继承了小明的属性(姓名,年龄),和方法(自我介绍),并重写了introduce方法
public class Hong extends Ming {
private int score;
public int getScore() {
return score;
}
public void setScore(int age) {
this.score = score;
}
@Override
public void introduce() {
System.out.println("My name is "+getName()+",I am "+getAge()+" years old,My code is very good!");
}
public void test() {
System.out.println("Your grades are"+getScore());
}
}
当我们新建Hong对象引用introduce方法时,将执行子类重写的方法。
注意:
Ø重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型。
Ø重写方法不能使用比被重写方法更严格的访问权限。(例如不能将public改为protected,但可将protected改为public)。
3.super 与 this, final ,static关键字
①final
当用final修饰一个类时,表明这个类不能被继承。修饰一个方法时,该方法不能被重写。修饰属性变量时该变量为常量,不能修改,只能在定义时初始化或者构造方法中初始化。
②static
static修饰方法时,表示方法属于类,称为静态方法,不用定义对象可直接调用。
class A{
final int i = 0;
public static void out() {
System.out.println("7777777");
}
}
//调用静态方法
class B {
public static void main(String[] args) {
A.out();
}
}
static修饰变量时,该变量也属于类,称为静态变量,也可直接调用。
注意:静态方法中只能调用本类中的静态变量和静态方法。
③this
我们在写类属性的set方法用过。他可以用来引用成员变量,成员方法,也可以引用构造方法。
class A{
private int i;
A(){
System.out.println("无参构造函数");
}
A(int i){
this();//引用构造函数(必须写在第一行)
this.i = i; //引用成员变量
}
public void out() {
System.out.println("7777777");
}
public void output() {
this.out(); //引用成员方法
}
}
④super
我们可以通过super关键字来实现对父类(非private)成员,方法的访问,也可以调用父类的构造器。如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器, 如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。
class A{
private int i;
A(int i){
this.i = i;
}
public void out() {
System.out.println("7777777");
}
}
class B extends A{
public B(int i) {
super(i); // 调用父类构造函数(必须写在第一行)
super.out(); //调用父类方法
}
}
————————————————
参考资料
1.https://blog.youkuaiyun.com/Yang_RT/article/details/83115779
2.https://www.runoob.com/java/java-inheritance.html