继承性


继承是面向对象中的第二大特点,其核心的本质在于可以将父类的功能一直沿用下去。

为什么需要有继承?

为了更好的区分出之前学习的概念与现在程序的区别,下面通过两个具体的代码来进行研究,例如现在给两个类:Person、Student,按照原始方式,程序代码如下:
在这里插入图片描述
学生是人,出现重复代码的核心问题是两个类之间没有联系。

使用继承解决问题

在Java中可以利用继承的概念实现父类代码的重用问题,程序中可以使用extends关键字实现继承操作定义,其使用的语法如下:

在这里插入图片描述
范例:使用继承来解决问题

class Person{
	private String name;
	private int age;
	public void setName(String name){
		this.name = name;
	}
	public void setAge(int age){
		this.age=age;
	}
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
}
class Student extends Person{//Student是Person的子类
	//此时并没有在Student类中定于任何操作
}
public class Hello {
	public static void main(String args[]){
		Student stu = new Student();//实例化子类对象
		stu.setName("张三");//通过Person类继承而来
		stu.setAge(12);//通过Person类继承而来
		System.out.println("姓名:"+stu.getName()+",年龄:"+stu.getAge());
	}
}

可以发现,子类完整的继承了父类的属性及方法,但是子类可以对父类的属性和方法进行扩充。
范例:扩充父类

class Student extends Person{//Student是Person的子类
	//此时并没有在Student类中定于任何操作
	private String school;//子类自己扩充属性
	public void setSchool(String school){
		this.school=school;
	}
	public String getSchool(){
		return this.school;
	}
}
public class Hello {
	public static void main(String args[]){
		Student stu = new Student();//实例化子类对象
		stu.setName("张三");//通过Person类继承而来
		stu.setAge(12);//通过Person类继承而来
		stu.setSchool("清华大学");//Student类自己扩充的方法
		System.out.println("姓名:"+stu.getName()+",年龄:"+stu.getAge()+",学校:"+stu.getSchool());
	}
}

在这里插入图片描述
通过继承实现发现:

  • 父类的功能可以延续到子类继续使用,这样在某些父类不能修改的情况下可以利用子类进行扩充;
  • 子类至少会拥有父类的方法和属性。

继承的限制

虽然继承的核心目的在于扩充类中已有的功能,但是在实际开发中,使用Java仍有若干限制。
限制一: Java不允许多重继承,也就是说一个子类只能继承一个父类

  • 因为C++支持多继承,也就是说一个子类可以同时继承多个父类。
    范例:错误的继承操作
class A{}
class B{}
class C extends A,B{}

为什么会出现这样的代码,其实本质上就是希望C类能够同是继承A类和B类的方法,但是由于这样的做法与现实生活有冲突,所以从Java的角度就屏蔽了,但是有解决方案。虽然Java不允许多重继承,但是却允许多层继承。以下代码是正确的。

class A{}
class B extends A{}
class C extends B{}

此时C类就具备A类和B类的全部定义,但是从实际出发,这样的继承不要超过三层。
限制二:子类在继承父类之后会将父类的全部结构继承下来,但对于私有操作属于隐式继承,而所有非私有操作属于显示继承。
范例:观察显示继承

class A {
	private String name;
	public void setName(String name){
		this.name=name;
	}
	public String getName(){
		return this.name;
	}
}
class B extends A{}
public class Hello{
	public static void main(String args[]){
		B b = new B();
		b.setName("Jane");
		System.out.println(b.getName());
	}
}

现在对于子类B而言是存在有name属性的,但是这个属性子类并不能直接操作。
范例:子类B直接访问

class B extends A{
	public void print(){
		System.out.println(name);
	}
}

在这里插入图片描述
也就是说此时name属于隐式继承,而所有的setter方法属于显示继承。显示继承可以直接访问,但隐式继承只能间接访问,否则不能访问。
限制三:在实例化子类时会默认调用子类的无参构造方法,但是在执行子类构造前会首先自动实例化父类构造,为父类的对象实例化,也就是说父类对象永远早于子类对象的实例化。
范例:观察实例化过程

class A {
	public A(){
		System.out.println("***************************");
	}
}
class B extends A{
	public B(){
		System.out.println("############################");
	}
}
public class Hello{
	public static void main(String args[]){
		B b = new B();
	}
}

在这里插入图片描述
现在如果非要为子类加上一个调用父类构造的标记,那么就可以使用“supe()”的形式完成。

class B extends A{
	public B(){
		super();	//表示调用父类构造
		System.out.println("############################");
	}
}

在这里插入图片描述
证明在子类的构造中一直隐藏了一行“super”语句,但是在进行无参父类构造调用的时候,写上“super()”是没有意义的。往往是在父类没有提供无参构造时使用的。
范例:错误的代码

class A {
	public A(String name){
		System.out.println("***************************");
	}
}
class B extends A{
	public B(){
		//super();	//表示调用父类构造
		System.out.println("############################");
	}
}
public class Hello{
	public static void main(String args[]){
		B b = new B();
	}
}

在这里插入图片描述
可以发现现在使用隐含的“super()”并不合适,所以应该明确的调用指定参数的构造方法。

class A {
	public A(String name){
		System.out.println("***************************");
	}
}
class B extends A{
	public B(String name){
		super( name);	//表示调用父类构造
		System.out.println("############################");
	}
}
public class Hello{
	public static void main(String args[]){
		B b = new B("SMITH");
	}
}

一般情况下父类都会提供无参构造方法,这个时候可以在子类构造中不出现“super()”无参构造,但是如果此时父类中没有提供无参构造方法,那么此时子类就必须使用“super()”调用指定参数的构造方法。
分析:关于this()与super()的问题。
“this()”表示调用本类的其他构造方法,“super()”由子类调用父类指定的构造方法,并且这两条语句都必须出现在首行,也就是说这两条语句不能够同时出现。
范例:不让子类调用父类构造

class A {
	public A(){
		System.out.println("***************************");
	}
}
class B extends A{
	public B(){}
	public B(String name){
		this();	//表示调用父类构造
		System.out.println("############################");
	}
}
public class Hello{
	public static void main(String args[]){
		B b = new B("Smith");
	}
}

在子类的构造方法中出现了“this()”,这样就不会出现“super()”的默认执行,而转为调用本类的构造方法了,那么这样是不是可以不调用父类的构造方法了呢?不
在这里插入图片描述

总结

  • 继承的唯一好处就是进行功能上的扩充,并且Java只支持单继承
  • 子类对象实例化时一定要先实例化父类对象,而后在实例化子类自己的对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值