JAVA学习之——继承和派生

前言:

前面已经大致的介绍了一下面向对象的四大特性中的“抽象”和“封装”(封装只讲了一点点,有关访问权限的问题我会在后面的内容中补上),接下来就来涉足一点点“深水区”的内容——继承多态。这篇文章我将介绍一下继承。

正文:

现实生活中的继承:

既然是“面向对象”思想中的继承,那当然要首先提一下我们现实生活中的“对象”继承的实例了。俗话说“子承父业”,即孩子可以继承父母的所有财产等物。古有皇位世袭制度,作为皇子来说,很多的江山都可以不用自己去打,而直接从父皇那继承过来。现有王校长玩累了就可以回家继承自己家中的万贯家产。总结一下现实中的继承一贯做法:XXX可以不用自己做,可以直接拿来用。无数的现实实例都可以体现出继承这一思想和概念。

编程的面向对象思想中的继承:

继承的作用(优点、好处)

与现实生活类似,面向对象中的继承也是贯彻了——
代码可以不用自己写,可以直接拿来用这一思想。
所以面向对象思想中继承的最大优点与好处也就是——*减少代码量,可以直接把别人写好的代码调过来用,从而实现不用自己写(增强代码的复用性)的目的。

继承的基本语法

class 类名 extends 父类(超类名)
{
}
语法很简单,让我们根据后面实际例子来理解它

继承的运用:

先来举个实际应用的例子吧!
以下为我要定的需求:
要定义一个属性包含有姓名和id的Person类,方法包含一个sayHi()方法用于输出属性。
然后再定义一个属性包含有姓名和id的Teacher类,方法包含一个sayHi()方法用于输出属性和一个teach()方法用于说明职业。
最后再定义一个属性包含有姓名和id的Doctor类,方法包含一个sayHi()方法用于输出属性和一个teach()方法用于说明自己的技能。
最后在测试类中分别new 对象进行测试以输出信息和方法。

如果按照我们前面所说的内容来做的话,大致代码是这样的:

不用继承的话
public class TestDemo {

	public static void main(String[] args) {
		Person p=new Person("张三",10086);
		p.sayHi();
		System.out.println("---------------");
		Teacher t=new Teacher("张三",10086);
		t.sayHi();
		t.teach();
		System.out.println("---------------");
		Docter d=new Docter("张三",10086,"开刀");
		d.sayHi();
		d.cut();
		System.out.println("---------------");

	}

}
class Person {
	String name;
	int id;
	Person(String name,int id)
	{
		this.name=name;
		this.id=id;
	}
	void sayHi()
	{
		System.out.println("我的名字是"+name+"我的id是"+id);
	}
}
class Teacher
{
	String name;
	int id;
	Teacher(String name,int id)
	{
		this.name=name;
		this.id=id;
		
	}
	void sayHi()
	{
		System.out.println("我的名字是"+name+"我的id是"+id);
	}
	void teach()
	{
		System.out.println("我的职业是老师");
	}
}
class Docter
{
	String name;
	int id;
	String skill;
	Docter(String name,int id,String skill)
	{
		this.name=name;
		this.id=id;
		this.skill=skill;
	}
	void sayHi()
	{
		System.out.println("我的名字是"+name+"我的id是"+id);
	}
	void cut()
	{
		System.out.println("我会"+skill);
	}
}

然后经过编译运行,得到了如下输出结果:
在这里插入图片描述
这样看输出结果的话,的确是满足了我们前面说的需求。但是不得不说,这几个类定义的属性和方法中,有很多都是重复定义的。比如说Person类的姓名、id属性和sayHi()方法,这些成员在后面的Teacher类和Doctor类均有定义和出现,而且都是一模一样的出现形式和作用。所以说,按照上面的代码来实现的话,我们做了很多不必要的重复操作。

使用继承后

为了实现代码的重用,减少代码的重复。我们尝试着运用前面所说的继承的思想来实现一下。
把上面的代码修改过后,内容如下:

public class TestDemo {
	public static void main(String[] args) {
		Person p=new Person("张三",10086);
		p.sayHi();
		System.out.println("---------------");
		Teacher t=new Teacher("张三",10086);
		t.sayHi();
		t.teach();
		System.out.println("---------------");
		Docter d=new Docter("张三",10086,"开刀");
		d.sayHi();
		d.cut();
		System.out.println("---------------");

	}

}
class Person {
	String name;
	int id;
	Person(String name,int id)
	{
		this.name=name;
		this.id=id;
	}
	void sayHi()
	{
		System.out.println("我的名字是"+name+"我的id是"+id);
	}
}
class Teacher extends Person
{
	Teacher(String name,int id)
	{
		super(name,id);//1
	}
	
	void teach()
	{
		System.out.println("我的职业是老师");
	}
}
class Docter extends Person
{
	String skill;
	Docter(String name,int id,String skill)
	{
		super(name,id);//1
		this.skill=skill;//2
	}
	void cut()
	{
		System.out.println("我会"+skill);
	}
}

在这里插入图片描述
由此可知,同样的,运行结果还是与上面一样。

运用继承后的代码分析

接下来我们来深入分析一下这段修改过后的代码中的Teacher类。(前面的测试类和Person类因为没有做任何改动,Doctor类与Teacher类同理,所以就不再分析了)
将上面修改前后的代码进行对比,首先是Teacher类的代码:

修改前(没用继承的时候)

class Teacher
{
	String name;
	int id;
	Teacher(String name,int id)
	{
		this.name=name;
		this.id=id;
		
	}
	void sayHi()
	{
		System.out.println("我的名字是"+name+"我的id是"+id);
	}
	void teach()
	{
		System.out.println("我的职业是老师");
	}
}

修改后(用了继承后)

class Teacher extends Person
{
	Teacher(String name,int id)
	{
		super(name,id);//1
	}
	void teach()
	{
		System.out.println("我的职业是老师");
	}
}

对比这两段代码,很明显的可以看出来,除了在Teacher的类名后按照前面所说的语法加了个extends Person之外。我还把其中的name和id属性的定义都删了,然后把构造方法里也删减了显式的赋值部分,取代它的是行super(name,id),与此同时,sayHi()方法也没有了。
在这里我们回忆一下最开始介绍的继承的思想——“XXX写的代码,我不用写,我直接拿来用。”
再结合前面前后2次的输出结果都是一模一样的可以看出来,父类Person中定义的姓名,id和sayHi()方法虽然不是我们自己写的,但是我们也是可以直接调用的。这样也就可以解释我为什么没有在Teacher类中定义姓名和id属性,却仍然有确定的姓名和id输出的问题了。
解决了父类的姓名和id都能够被子类正常调用后。那么再来看看修改后我标注为1的super(name,id);//1部分。首先,super是一个关键字,在这意为父类,超类的意思(与上篇文章所说的this(当前类)的作用差不多,由于上篇文章已经解释过了,这里就不展开了)。这句话就是实现了将子类的从父类继承而来的属性,把这些属性值通过父类已有的构造方法实现构造的意思。这样子类的构造方法也就可以“少干点活,从而专注于构造自己特有的属性和变量的工作了(如上文修改过后的Doctor类中的构造方法:在那里,它把从父类继承过来的属性和变量发送给父类的构造方法,由父类进行构造,除此之外,它只用专门的对自己特有的skill属性进行赋值构造)”。
与类的成员变量与属性同理,对于子类来说,只要在类中特别定义出自己所特有的成员方法就行了,从父类那继承过来的方法,子类也一样可以正常使用(即继承过来了,也就属于子类的方法了)。
如下面这段代码中B类的成员方法其实是有a()、b()两个方法的(从父类继承过来的)。

class A
{
	void a(){}
}
class B extends A
{
	void b(){}
}

结语:

最后来总结一下继承的相关内容
作用:增强代码的复用性可迁移性,减少不必要的重复
特征:
1)运用extends关键字
2)子类可以把父类中定义的所有成员都全盘接收,使之成为自己的成员并使用。(暂时不考虑private权限的情况)
3)子类构造之前必须前构造父类

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值