4继承知识点.docx
- 文档编号:27505227
- 上传时间:2023-07-02
- 格式:DOCX
- 页数:24
- 大小:77.66KB
4继承知识点.docx
《4继承知识点.docx》由会员分享,可在线阅读,更多相关《4继承知识点.docx(24页珍藏版)》请在冰豆网上搜索。
4继承知识点
本章是对前面所涉及到面向对象的知识做一个系统的学习,比较简单。
主要是思想上得到提高
1.什么叫继承?
它有什么优点?
什么时候用?
大家都看过《西游记》。
《西游记》里有唐僧和孙悟空。
唐僧是孙悟空的师傅,所以孙悟空就要有哪些行为呢?
定义一个类去描述孙悟空。
publicclass孙悟空{
publicvoid参佛(){
//……
}
publicvoid念经(){
//……
}
publicvoid西天取经(){
//……
}
publicvoid守戒律(){
//……
}
publicvoid降妖(){
//……
}
}
这时候,到了高老庄了,又收了猪八戒作徒弟,猪八戒有什么方法呢?
publicclass猪八戒{
publicvoid参佛(){
//……
}
publicvoid念经(){
//……
}
publicvoid西天取经(){
//……
}
publicvoid守戒律(){
//……
}
publicvoid牵马(){
//……
}
}
这时候,到了流沙河了,又收了沙和尚作徒弟,沙和尚有什么方法呢?
publicclass沙和尚{
publicvoid参佛(){
//……
}
publicvoid念经(){
//……
}
publicvoid西天取经(){
//……
}
publicvoid守戒律(){
//……
}
publicvoid挑行李(){
//……
}
}
上面三个类都有参佛、念经、西天取经、守戒律这些方法。
这些方法都是重复定义的。
为了达到代码的可重用性,我可以把这些相同的属性和方法给提取出来,单独作一个类:
徒弟类。
然后由孙悟空、猪八戒、沙和尚来继承于它,在每个子类里描述和父类不同的部分就行了。
上面的代码可改为
publicclass徒弟{
publicvoid参佛(){
//……
}
publicvoid念经(){
//……
}
publicvoid西天取经(){
//……
}
publicvoid守戒律(){
//……
}
}
publicclass孙悟空extends徒弟{
publicvoid降妖(){
//……
}
}
publicclass猪八戒extends徒弟{
publicvoid牵马(){
//……
}
}
publicclass沙和尚extends徒弟{
publicvoid挑行李(){
//……
}
}
这样的代码看起来就简洁多了。
当我们在父类里定义的方法和属性,子类都可以通过继承的方式拥有。
所以使用JAVA面向对象继承的特性,可以大大提高代码的重用性。
同时,这种方式也便于扩展,如果唐僧再收一个徒弟,也只需继承徒弟这个父类,在子类描述子类自己所拥有的特殊方法和属性就行了。
有句俗话:
种瓜得瓜,种豆得豆。
说明如果一个类继承于另一个类时,那么就会拥有被继承类大部分方法和属性。
一个新类可以从现有的类中派生,这个过程称为类继承。
现有类称为新类的父类(基类),新类称为现有类的子类(派生类)
◆继承可提高代码的重用性,使用extends关键字来实现。
父类的方法和属性部分被子类的对象继承
那么是不是所有的类都可以被子类继承呢?
并不是这样,就象中国古代的太监一样,他是没有儿子的。
所以如果一个类被申明成final修饰符,那么这个类就不能被继承了。
有这样一个IQ问题:
阿刚有一天上街,看到一百块钱和一块肉,他不要一百块钱而要肉,这是为什么?
答案是阿刚是条狗。
这是利用了人的惯性思维,看到阿刚就以为他是个人,是人的子类,这样的话就应该有人的行为和方法,而做出选择一百块钱的动作。
如果我们事先知道阿刚是继承狗这个类的话,这个问题就没有问的意义了。
前面提到父类的方法和属性只能部分被子类对象继承。
那么哪些属性和方法可以继承,哪些又不能被继承呢?
举个例子:
父亲有属性和方法。
第一,父亲的外表,它可以被所有人访问到。
(public修饰符)。
第二,父亲脸上有颗痣,这是父亲特有的属性,不能由别人访问。
(private)第三,父亲的财产,只有父亲本身和儿子才能访问。
(protected)
所以子类只能继承可以被继承的属性和方法,那么什么样的修饰符能被子类所访问到
呢?
由上表可以看出,private修饰符的属性只能由本类调用,缺省成员可以由本类和同包内的其他类调用,protected成员可以由本类、同包内的其他类,以及不同包的子类访问。
而public修饰符成员可以被所有的类访问。
代码示例:
packagecom;
publicclassBase{
privatevoidmethod1(){}//1
voidmethod2(){}//2
protectedvoidmethod3(){}//3
publicvoidmethod4(){}//4
}
packagecom
publicclassA{
A(){
Basebase=newBase();
base.method1(){}//这是Base私有方法,其他类不能访问
base.method2(){}//A和Base同属一个包,可以访问缺省成员
base.method3(){}//可以访问protected成员
base.method4(){}//public能被所有类访问
}
}
packagetem;
publicclassMyCastextendsBase{
MyCast(){
Basebase=newBase();
base.method1(){}//这是Base私有方法,其他类不能访问
base.method2(){}//MyCast和Base同属不同包,不能访问缺省成员
base.method3(){}//MyCast是Base子类,可以访问protected成员
base.method4(){}//public能被所有类访问
}
}
packagetem
publicclassB{
B(){
Basebase=newBase();
base.method1(){}//这是Base私有方法,其他类不能访问
base.method2(){}//B和Base同属不同包,不能访问缺省成员
base.method3(){}//B不是Base子类,不能访问protected成员
base.method4(){}//public能被所有类访问
}
}
标志
可见性类型
+Public
#Protected
-Private
~Package
◆父类的构造方法不能被它的子类继承.
◆子类对象构建时,会先去调用父类的构造方法。
(没有父亲,哪来的儿子),并且子类需要通过父类构造方法的调用来完成从父类继承下来的属性初始化。
◆可以使用super()显式地调用父类的构造方法,如果父类构造方法有参数,也可以在括号中跟参数。
◆构造方法一旦有显示的申明,则隐式的构造方法就不存在了。
这样,如果父类有显示、带参数的构造方法,则子类必须使用super(参数)显示的调用父类的构造方法
◆如果子类没有定义构造方法,系统会默认地添加一个无参的构造方法,并在第一句自动调用父类不带参数的构造方法super()。
代码示例:
publicclassFarther{
}
classChildextendsFarther{
publicChild(){
super();//子类在构建时会调用父类构造方法,使用super关键字,如果不写,则是调用父类无参构造方法,该语句应该在子类构造方法第一句
}
}
在讲到构造方法时,已经说到,如果一个类有显示的构造方法,则默认的构造方法就不存在了。
因此,如果父类有显示的带参数构造方法,子类构造方法必须显示的调用父类的构造方法。
publicclassFarther{
publicFarther(inti){
}
}
classChildextendsFarther{
publicChild(){
}
}
这样的代码是不能通过编译的,因为子类在构建时,先得去调用父类的构造方法。
如果子类构造方法什么都不写,默认是super()调用父类无参的构造方法。
但上例中,父类有个有参数的构造方法,无参数的构造方法就不存在了。
所以子类构造方法必须显示的调用父类的构造方法。
应该改为:
classChildextendsFarther{
publicChild(){
super(0);
}
}
构造方法修饰符的问题
构造方法修饰符,也是public、protected、缺省、private。
不同的修饰符代表可访问性。
如果一个类构造方法被申明为私有的,那么这个类是不能被继承的,因为子类无法访问到父类的构造方法。
如果是缺省的,表示本包的其他类可以访问。
如果是protected表示本包其他类和不同包的子类可以访问。
public则是所有类都能访问。
注意protected修饰构造方法完全是允许的。
这表示子类可以调用父类的构造方法。
注意是调用,而不是继承,构造方法是无法继承的。
注意:
在JAVA中,类的继承是单根继承,就是说一个类如果继承了另一个类之后,就不能再继承其他类了。
2.什么叫多态?
JAVA里的多态性是怎么体现的?
多态概念:
允许一个父类变量引用子类,允许一个接口类型变量引用实现类对象。
反过来却不行。
具体表现为重载和重写。
举例说明:
我们说马是动物,牛也是动物,人也是动物。
说明动物这个类型可以指向不同类的对象。
但反过来,动物是马,动物是牛这个说法就不成立了。
因为马这个类型不能指向动物。
所以父类的类型可以指向子类的对象,但子类的类型不能指向父类的对象
以前有个城门上贴了一个告示:
不能骑马入城。
有个叫东孙龙的家伙就骑着一匹白马走进了城,官差就叫住了他:
没看见告示吗?
不能骑马入城。
东孙龙说,我骑的是白马,又不是马。
这个例子用面向对象的思想来看,东孙龙是没有承认白马是马的子类。
马是一个父类,告示这样说,是指的马和马的子类对象都不能进城。
这也说明父类的变量可以指向子类的对象。
publicclassFarther{
publicstaticvoidmain(String[]args){
//父类的变量可指向不同子类的实例
Fartherfarther=newChildOne();//指向第一个子类实例
farther=newChildTwo();//指向第二个子类实例
farther=newChildThree();//指向第三个子类实例
}
}
classChildOneextendsFarther{
}
classChildTwoextendsFarther{
}
classChildThreeextendsFarther{
}
从上面的例子可以看出,一个父类的变量可以指向不同子类的实例。
那么这样的话,怎么判断父类到底指向的哪一个子类的实例呢?
使用instanceof的用于判断一个对象的实际类型,这个运算符用于判断一个对象是否是指定的类型。
返回一个布尔值,是true表示匹配该类型,是false表示不匹配该类型。
如上例中,我们要判断farther这个变量是否是ChildOne这个子类的对象,可以使用以下方法:
System.out.println(fartherinstanceofChildOne);
多态具体表现为重载和重写
有句俗话:
龙生九子,各个不同,说明即使是同一个父类的子类,它们也有不同的属性和方法。
1、重载:
这是同一个事物对不同的事件作出不同的反应。
用在程序里,就是在同一个类里有多个方法,方法名相同,但参数不同。
(参数不同,包括参数个数不同,参数类型不同,参数顺序不同)。
和返回类型无关。
publicclass人{
publicvoidlook(美女x){//看的方法,传入一个美女参数
System.out.println("枯木逢春");
}
publicvoidlook(食物x){//方法重载,这是类型不同
System.out.println("流口水");
}
publicvoidlook(美女y,intx){//方法重载,这是个数不同
System.out.println("春光满目");
}
publicvoidlook(intx,美女y){//方法重载,这是顺序不同
System.out.println("春情如电");
}
publicintlook(美女y){//这个方法不能通过编译,虽然看的方法返回类型不同,但参数和第一个方法完全一样,所以这不能叫做重载,系统会认为是相同的方法,不能通过编译
System.out.println("春色可餐");
return0;
}
}
以上例子,同样是人拥有的看的方法,但由于传入的参数不同,所以流露出不同的反应
2、方法的重写
这是不同的事物对同一个事件有不同的反应。
人有吃东西的方法,但不同的人吃的东西不一样。
重写在程序里体现在父类和子类之间。
父类有一个方法,当子类也拥有相同的方法时这就叫重写(方法名相同,参数相同,返回类型也相同)
publicclass人{
publicvoid爱好(){
System.out.println("吃东西");
}
}
class卫俊extends人{
publicvoid爱好(){//重写父类的方法,方法名相同,参数相同,返回类型也相同
System.out.println("玩游戏");
}
}
class杨琴extends人{
publicvoid爱好(){
System.out.println("绘画");
}
}
上面的例子,卫俊和杨琴都是人的子类,人有个爱好的方法,打出“吃东西”,但卫俊的爱好是“玩游戏”,杨琴的爱好是“绘画”。
这两个子类都重写了父类爱好的方法。
重写访问修饰符的问题
子类重写父类的方法,访问修饰符必须和父类的访问修饰符相同,或比父类访问修饰符更大。
那是因为在多态中我们常用父类的变量质量指向子类的对象。
如果父类的访问修饰符小于了子类的访问修饰符的话,很容易造成访问不了的结果。
缺省——protected——public
publicclass人{
void爱好(){
System.out.println("吃东西");
}
}
class卫俊extends人{
publicvoid爱好(){//子类访问修饰符比父类更大
System.out.println("玩游戏");
}
}
子类重写父类的方法后,在调用时优先调用子类的方法。
子类没有该方法时,才去调用父类的方法。
publicclass人{
void走(){
System.out.println("用腿走路");
}
void爱好(){
System.out.println("吃东西");
}
publicstaticvoidmain(String[]args){
人x=new卫俊();
x.爱好();//结果是“玩游戏”,因为虽然x是父类的变量,但指向是卫俊这个子类的对象,而卫俊这个子类重写了爱好这个方法,所以优先调用子类的方法
x.走();//结果是“用腿走路”,因为卫俊这个子类并没有重写父类走的方法,所以调用的是继承于父类走的方法
}
}
class卫俊extends人{
publicvoid爱好(){
System.out.println("玩游戏");
}
}
并不是父类所有的方法都能被重写,当一个方法申明为final修饰符时,这个方法就不能被子类重写了。
publicclass人{
finalvoid爱好(){
System.out.println("吃东西");
}
}
class卫俊extends人{
publicvoid爱好(){//该语句非法,因为父类爱好的方法被申明为final,那么子类就不能重写。
System.out.println("玩游戏");
}
}
final用法总结:
final这个修饰符可用于类前面,方法前面,和变量前面。
用于类前面,表示这个类不能被继承;用于方法前面,表示方法不能被子类所重写;用于变量前面,如果是基本数据类型,表示该变量是个常量,它的值不能被更改。
如果变量的为引用数据类型,表示变量的引用不能再指向新的对象。
子类重写了父类的方法也可以通过super这个关键字调用父类的方法。
publicclass人{
void爱好(){
System.out.println("吃东西");
}
}
class卫俊extends人{
publicvoid爱好(){
System.out.println("玩游戏");
}
/**
*构造方法
*/
public卫俊(){
爱好();//调用爱好的方法,因为子类重写了父类的方法,所有优先调用子类的方法,这时打出“玩游戏”。
super.爱好();//这是调用父类爱好的方法,打出吃东西
}
}
上面的例子有个问题,人是有爱好的,但每个人的爱好都不一样。
这样的话,每个子类都要重写父类的方法。
父类就说了,子类既然都要重写父类的方法,父类就没有必要去实现它。
父类只是把它定义出来,至于实现,则由子类去实现。
这样父类定义方法却不实现,这样的方法叫抽象方法,使用abstract修饰符。
而这样的类叫抽象类,也得使用abstract修饰符。
一个类一旦定义为抽象类,就不能被实例化了。
即不能通过new类名()的方式获得这个类的对象。
如果一个普通类继承于一个抽象类,那么必须实现父类里面定义的所有抽象方法。
这样的话,抽象类就可以起一个模版作用。
在父类里把抽象方法定义好,子类在继承于它时,必须实现父类的抽象方法。
这样可以规范子类的方法。
(方法名不能随便乱改)
小时候玩的动物尺子一样,定一个动物形状的模版凹槽,孩子要画图的时候,用画笔沿着尺子的凹槽画出来就是一个动物。
至于动物是什么颜色的,就要看画笔是什么颜色的。
这种思想对于以后JAVA的学习至关重要。
想象一下,在多个人同时开发一个项目的时候。
为了达到统一,因此设计的时候,就可以事先定义好一些抽象类和一些抽象方法,交给不同的人去实现,这样的话,开发的人就必须实现给定的方法,就不能自己随心所欲了。
publicabstractclass人{
publicabstractvoid爱好();//抽象方法。
只有定义没有实现。
那么什么是定义呢?
方法后面直接是分号结束,这就是定义。
而加{}则是实现
publicabstractvoid吃东西();
publicvoid走(){//抽象父类可以定义方法,也可以实现方法
System.out.println("用腿走路");
}
}
class卫俊extends人{
publicvoid爱好(){//子类继承于抽象父类,必须实现父类定义所有抽象方法
System.out.println("玩游戏");
}
publicvoid吃东西(){
System.out.println("吃面");
}
}
class杨琴extends人{
publicvoid爱好(){//只要是继承于抽象父类,那么父类里每个抽象方法都必须实现
System.out.println("绘画");
}
publicvoid吃东西(){
System.out.println("吃鱼");
}
}
◆private方法和static静态方法以及构造方法不被声明为abstract.
7.什么是接口?
为什么要使用接口?
接口是抽象类的特例,在抽象类中的方法可以实现,也可以用抽象方法定义,但在接口中就只能是定义,不能有实现。
定义接口,使用关键字interface
interfaceA{//定义接口
publicvoidd();//定义接口方法
}
接口里的方法都是public公有方法,即使不写,默认也是pubic的。
其他的修饰符都无效。
interfaceA{
publicvoida();//申明接口方法为public,合法
voidb();//使用缺省修饰符定义接口,默认也是public,合法
//privatevoidc();//非法语句,接口修饰符,只能为public或不写
//protectedvoidd();//非法语句,接口修饰符,只能为public或不写
}
接口定义出来,是要被类所实现的。
定义一个类实现接口,就得实现接口里定义的所有的方法。
使用关键字implements
classBimplementsA{
publicvoida(){
……
}
publicvoidb(){
……
}
}
接口是Java编程一项重要的技术,通过它可以实现多态,同时它也弥补了Java单一继承的不足。
之前说到类是单根继承,一个类继承了另一个类之后,就不能继承其他类了。
但现实生活中很多事物都同时拥有很多类的特性。
为了解决这个问题,在JAVA中使用接口来进行描述这些事物不同的行为,在JAVA中一个类可以实现多个接口。
这样的话,这个类就得实现每个接口所定义的方法。
interface陆生动物{
publicvoid陆地生活();
publicvoid有腿();
}
interface水生动物{
publicvoid产卵();
}
class青蛙implements陆生动物,水生动物{
publicvoid有腿(){//实现陆生动物接口方法
}
publicvoid陆地生活(){//实现陆生动物接口方法
}
publicvoid产卵(){//实现水生动物接口方法
}
}
接口中可以定义变量,但接口中的变量是公共的静态的常量。
(publicstaticfinal)
接口可以继承接口,继承之后会拥有父接口所定义的方法。
集合框架JCF就是一个例子。
Conllection是父接口,List和Set是子接口。
接口可以是多继承。
一个类要实现一个接口,那么就得实现这个接口和这个接口父接口所定义的所有方法。
int
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 继承 知识点
![提示](https://static.bdocx.com/images/bang_tan.gif)