八、面向对象三大特征(二)—— 继承

时间:2021-05-02 19:52:27

继承的含义

    面向对象编程,最重要的就是类的设计。如何将一类事务抽象成所需要的类是我们最常考虑的,继承是面向对象设计的第二大特性,通过继承,我们可以将原来的类进行了复用和扩充了特性,而类的继承机制,就大大增加了代码的可重用性和可扩充性。

    在java中,大家一定要记住,java只支持单继承机制,即一个类只能最多继承于另一类,也就是说,一个子类最多只能有一个父类,这里就很好理解了,一个孩子的父亲只能有一个对吧O(∩_∩)O。

实现继承的格式

   class 子类名 extends 父类;


下面我给大家写两个例子,让大家明白继承的好处,即演示一下代码的重用性和可扩充性问题

    例如:有一个类Person,我们作为父类,有姓名和年龄这两个属性,还有说话的行为。这时候有一个学生类,他有三个属性姓名,年龄,学校,还有说话和学习的行为。当没有继承的时候,我们来写一下

代码演示:

package demo;

import com.sun.media.jfxmedia.control.VideoDataBuffer;
import com.sun.org.apache.bcel.internal.generic.NEW;

class People{
	private String name;
	private int age;
	
	public People(String name, int age) {
		
		this.name = name;
		this.age = age;
	}
	
	public void talk(){
		System.out.println("我的名字叫"+this.name+",我的年龄是"+this.age);
	}
}

class Student{
	private String name;
	private int age;
	private String school;
	
	public Student(String name, int age,String school) {
		this.name = name;
		this.age = age;
		this.school = school;
	}
	
	public void talk(){
		System.out.println("我的名字叫"+this.name+",我的年龄是"+this.age);
	}
	
	public void study(){
		System.out.println("我在"+this.school+"学校读书");
	}
}
public class InheritDemo {
	public static void main(String[] args){
		Student stu = new Student("bigdodo", 20, "北大");
		stu.talk();
		stu.study();
	}
}

代码讲解:这里并没有用上继承,而是创建了两个类,然后只用上了我们需要的学生类,下面给大家演示一下继承机制


代码演示:

package demo;

class People{
	private String name;
	private int age;
	
	public People(String name, int age) {
		
		this.name = name;
		this.age = age;
	}
	
	public void talk(){
		System.out.println("我的名字叫"+this.name+",我的年龄是"+this.age);
	}
}

class Student extends People{
	private String name;
	private int age;
	private String school;
	
	public Student(String name, int age,String school) {
		super(name, age);
		this.school = school;
	}
	
	public void study(){
		System.out.println("我在"+this.school+"学校读书");
	}
}
public class InheritDemo {
	public static void main(String[] args){
		Student stu = new Student("bigdodo", 20, "北大");
		stu.talk();
		stu.study();
	}
}

代码讲解:这里我们并没有对父类People做出修改和操作,我们对Student类修改了三个地方,第一个地方,在类名边上我们用extends,声明了我们继承了People类,也就告诉了java我们的Student是People的子类,第二个地方,修改了Student类的构造方法,我们加入了super关键字,将其中两个参数传给父类的构造器了。这里大家先记得是这样使用的,我们下面接着来讲为什么。最后修改的一个地方是,我们将子类的talk()方法拿掉了,但是在使用的时候发现,我们还是可以用stu.talk(),调用这个方法,这里其实是我们调用了父类的talk()方法,我们将它继承过来了,所以不需要自己写,直接调用父类的方法即可。



继承的限制

限制1

      java可以单继承,不能够多重继承,但是可以多层继承

八、面向对象三大特征(二)—— 继承


八、面向对象三大特征(二)—— 继承

限制2

   从父类继承的私有成员,不能被子类直接使用

子类在继承父类的时候会将父类的全部成员(包括属性和方法)继承下来,但是对所有的非私有(private)成员属于显示继承,而对于所有的私有成员采用隐式继承,即子类是不可见的,子类无法直接操作访问这些属性,必须通过getter和setter方法来间接的操作


限制3

子类在进行对象的实例化时候,从父类继承而来的数据成员(属性),需要先调用父类的构造方法来初始化,然后再用子类的构造方法来初始化本地数据成员。

八、面向对象三大特征(二)—— 继承

八、面向对象三大特征(二)—— 继承

限制4

    final关键字修饰的类不可以被继承,final有最终的,终结的意思,大家只需要记住即可。


根据限制3,我们来做一个简单的测试

代码演示:

package demo;

class People{

	public People(){
		System.out.println("调用了父类的构造方法");
	}
}

class Student extends People{

	public Student() {
		System.out.println("调用了子类的构造方法");
	}
}

public class ConstructorDemo {
	public static void main(String[] args) {
		Student student = new Student();
	}
}

代码结果:

八、面向对象三大特征(二)—— 继承


super关键字

   通过上面的例子,我们可以得到初步结论,super关键字的主要功能是完成子类调用父类中的属性或方法,调用super(),必须卸载子类构造方法的第一行,否则编译不通过,会出现报错。实际上,通过上面的例子,可以知道,子类构造方法第一条语句,都是隐式的调用了super()。super关键字除了调用父类的构造方法,还可以调用父类的属性和方法

调用父类的属性:super.属性名;

调用父类的方法: super.方法名();



方法的重写(覆写)

   回到第二代码演示,我们记得,在继承的时候,因为父类有了talk()方法,所以我们在子类Student类中并没有写出talk()方法,但是如果这个学生是外国人怎么办?其实在java中给我们提供了方法重写的功能

代码演示:

package demo;

class People{
	private String name;
	private int age;
	
	public People(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public void talk(){
		System.out.println("我的名字叫"+this.name+",我的年龄是"+this.age);
	}
	
}

class Student extends People{
	private String name;
	private int age;
	private String school;
	
	public Student(String name, int age,String school) {
		super(name, age);
		this.school = school;
	}
	
	public void talk(){
		System.out.println("my name is "+this.name+" and i'm "+this.age+"years old");
	}
	
	public void study(){
		System.out.println("我在"+this.school+"学校读书");
	}

}
public class InheritDemo {
	public static void main(String[] args){
		Student stu = new Student("bigdodo", 20, "北大");
		stu.talk();
		stu.study();
	}
}

代码结果:

八、面向对象三大特征(二)—— 继承

代码讲解:我们发现,这时候我们的name值和age值都没法取到,为什么呢?

    原因是这样的,我们将name和age属性是通过super()关键字调用的父类的构造方法的,那这两个私有的属性在子类是不可见的,这里大家应该想起来了吧,父类的私有属性,在子类是隐式不可见的,需要通过getter方法和setter方法才能取到,这时候我们修改代码如下


代码演示:

package demo;

class People{
	private String name;
	private int age;
	
	public People(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public void talk(){
		System.out.println("我的名字叫"+this.name+",我的年龄是"+this.age);
	}

	public String getName() {
		return name;
	}

	public int getAge() {
		return age;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
}

class Student extends People{
	private String name;
	private int age;
	private String school;
	
	public Student(String name, int age,String school) {
		super(name, age);
		this.school = school;
	}
	
	public void talk(){
		System.out.println("my name is "+super.getName()+" and i'm "+super.getAge()+"years old");
	}
	
	public void study(){
		System.out.println("我在"+this.school+"学校读书");
	}

}
public class InheritDemo {
	public static void main(String[] args){
		Student stu = new Student("bigdodo", 20, "北大");
		stu.talk();
		stu.study();
	}
}

代码讲解:在这我们在父类方法里面写上了getter()和setter()方法,这时候子类的talk()方法里我们就可以通过super关键字调用父类的getter()方法,来获取到父类私有属性里的值了


    总结点评:java的面向对象第二大特性——继承,虽然内容有点多,但其实很实用,并且你会一直用到,所以本章节读者们应该仔细阅读,并多敲敲代码,发现问题,这时候的每次发现问题都不可怕,能发现问题都是进步,可以自己尝试解决,解决不了,也欢迎大家评论留言bigdodo会给大家耐心解答。感谢你的阅读!