0
点赞
收藏
分享

微信扫一扫

Java面向对象编程——继承

i奇异 2022-04-13 阅读 73
javaeclipse

目录

方法的覆盖

super关键字


        继承是一种由已有的类创建新类的机制。利用继承,我们可以先创建一个共有属性的一般类,再根据该一般类创建具有特殊属性的新类,新类继承一般类的状态和行为,并根据需要增加自己新的状态和行为。由继承得到的类称为子类或派生类,被继承的类称为父类、基类或超类。Java 不支持多重继承,子类只能有一个父类。

先看以下代码:

public class Saloon_car {
	String engine;	//引擎
	String Wheel;	//车轮
	String airbag;	//货舱
	
	public void run(){		//方法
		//定义车跑动的行为
	}
}
public class Truck {
	String engine;	//引擎
	String Wheel;	//车轮
	String carport;		//安全气囊
	
	public void run(){	//方法
		//定义车跑动的行为
	}
}

        上面写了两个类的定义,我们会发现,这两个类有很多重复的属性和行为,这不仅带来了代码的繁杂,产生大量冗余代码,而且更重要的是,程序变得难以驾驭,我们很难对程序进行更新。

        如果现在我们要在创建一个或多个类属性和行为相似的类,就要单独写多个重复的属性和行为如果这样的话会造成代码冗余。

那么如何解决这样的问题,就是要使用继承

继承使用的关键字是extends

首先可以写一个父类——Car,在定义将车,卡车类,它们拥有父类Car的所有特征,再加上自己独有的特性,形成Saloon_car,Truck.代码如下

//汽车类
public class Car {
	String engine;	//引擎
	String Wheel;	//车轮
    //....其他属性
	
	public void run(){		//方法
		//定义车跑动的行为
        System.out.println("汽车在奔跑!");
	}
}



//轿车类
public class Saloon_car extends Car{
    String airbag;    //安全气囊
}

//卡车类
public class Saloon_car extends Car{
    String carport;    //货舱
}

在上面代码,轿车类和卡车类继承后,拥有了汽车类中定义的所有属性和方法。我们可以测试一下

运行如下

方法的覆盖

        观察上图可以发现,不管是普通汽车,还是卡车和轿车,它们的运转都是一样的,结果均输出“汽车在奔跑!”,这是不恰当的。按道理来说,卡车和轿车的运转应该有自己的独立方式,不应当和普通汽车保持一致。也就是说,子类需要对父类的 run(方法加以改进,变成子类自己的 run()方法,这就需要在子类中重新编写 run()方法,覆盖父类的 run()方法,这种做法在 Java 中叫作方法的覆盖(overide),又称方法重写。

实例如下

//父类汽车类
public class Car {
	String engine; // 引擎
	String Wheel; // 车轮
	// ....其他属性

	public void run() { // 方法
		// 定义车跑动的行为
		System.out.println("汽车在奔跑!");
	}
}



//子类轿车类
public class Saloon_car extends Car {
	 String airbag;    //安全气囊
	 public void run() {	//不用父类方法,重新编写的run方法
		 //定义轿车
		 System.out.println("轿车在高速路上奔驰!");
	 }
}


//子类卡车类
public class Truck extends Car {
	String carport; // 货舱

	public void run() { // 不用父类方法,重新编写的run方法
		System.out.println("卡车在工地上忙碌!");
	}
}

        再次运行程序,这时结果就正常了,汽车、轿车、卡车分别以自己的方式在奔跑。方法覆盖要求:子类方法和父类方法同名,且参数相同。

        要注意重载和重写的区别,重载既可以发生于一个类,也可以发生于子类与父类之间(子类继承父类方法,同时完成方法重载),而重写,只能是子类重写父类方法。

super关键字

       学完继承后,我们注意到一个问题,在某些时候,子类需要调用父类的某些方法,如以下代码

public class Calculator {
	public void play() {
		System.out.println("完成四则运算功能");
		this.print();    //引用print()方法
	}

	public void print() {
		System.out.println("显示结果!");
	}
}


public class Computer extends Calculator {
	public void play() {
		System.out.println("完成四则运算功能");
		this.print();             //引用print()方法
		System.out.println("完成娱乐功能");
		this.print();            //引用print()方法
	}

	public static void main(String[] args) {
		Computer c = new Computer();    //实例化对象
		c.play();                        //引用play()方法
	}
}

         在 Calculator(计算器)类中,定义了 play)方法实现四则运算功能。子类 Computer(计算
了,我们知道,不管是计算器,还是计算机,它们在四则运算功能上是一样的,所以没必
要让计算机类重新实现一遍,完全可以直接使用父类已完成的功能,这样不仅使代码简洁,
更重要的是便于程序的更新。

public class Computer extends Calculator {
	public void computerCalc() {
		this.play();    //调用play()方法
		System.out.println("完成娱乐功能!");
		this.print();    //调用print()方法
	}

}

         这种做法是在 Computer 类内重新定义一个新方法 computerCalc(),因为 Computer类
继承了 Calculator 类,所以可以直接在其中调用 play0方法。
        虽然这种做法没有任何问题,但是不便于程序的阅读。若想在重写的同时能调用父类
的对应方法,该如何实现呢?答案就是 super 关键字。

        super关键字引用当前对象的直接父类中的属性和方法(用来访问直接父类中被隐藏的
属性和方法,经常在基类与派生类中有相同属性和方法定义时使用)。

public class Computer extends Calculator {
	public void play() {
		//System.out.println("完成四则运算功能");
		//this.print();
		super.play();	//调用父类的同名play()方法
		System.out.println("完成娱乐功能");
		this.print();
	}

	public static void main(String[] args) {
		Computer c= new Computer();
		c.play();
	}
}

         运行程序,发现结果与修改前是一样的,可见 super 关键字的功用绝非一般。
除了调用父类同名方法外,super 还广泛地运用于构造方法内,如下列代码

//Calculator类
public class Calculator {
	Calculator(){    //方法
		System.out.println("产生计算机!");
	}
}


//Computer类
public class Computer extends Calculator {
	Computer(){    //方法
		System.out.println("产生计算机!");
	}
}


//测试类
public class Test {
	public static void main(String[] args) {
		Computer comp = new Computer();    //对象实例化
	}
}

运行结果如下

        

 

        匪夷所思,在调用计算机类构造方法的同时,却也调用了计算器类的构造方法,其实,
这也是 super 关键字的原因。在子类的构造方法内,存在一个 super(用于调用父类的默认
构造方法。其实 Computer 类的完整写法如下

public class Computer extends Calculator {
	Computer() {
		super(); // 由系统自动生成,代表父类默认的构造方法
		System.out.println("产生计算机!");
	}
}

         发挥一下想象力,既然系统自动生成了 super()方法,那我们能不能自己自由书写 superl
呢?答案是肯定的,只不过要遵循如下原则:

  1. super 要放在第一行。
  2. super 所指引的构造方法在父类中必须要有。
  3. 如下代码
public class Employee {
	String name;    //属性

	public Employee(String name) {
		this.name = name;    //实参name赋值给当前类的name
	}
}


public class Manager extends Employee {
	String department;    //属性
	public Manager(String name,String department) {
		super(name);    //获取父类的name属性
		this.department = department;    //将参数的值赋值给当前类的department属性
	}
}

        在 Manager 类中,不需要再次书写“this.name = name”,而只需要把 name 参数通过
super()方法传递给父类的对应构造方法,由父类完成该参数的初始化即可。

举报

相关推荐

0 条评论