




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第六章
Java的继承
继承的概念
继承的实现变量隐藏与方法覆盖super关键字子类的构造顺序
final关键字
回忆:为什么要使用封装下面代码有什么问题?如何解决上面设计的缺陷?Dogd=newDog();d.age=1000;不合理的赋值
使用封装
回忆:什么是封装面向对象三大特征之一——封装封装的概念封装的好处封装:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问
隐藏类的实现细节只能通过规定方法访问数据方便参加控制语句方便修改实现回忆及提问构造方法的语法要求是什么?static和final的含义是什么?请画出下面Dog类的类图。回忆:类图使用类图描述类用于分析和设计“类”直观、容易理解-name:String-health:int-love:int+strain:StringDog+print():void“+”:public“-”:private“#”:protected·类名返回值类型类型属性名参数:名字:类型,名字:类型方法名为什么使用继承?这两个类图有什么问题?-name:String-health:int-love:int-strain:StringDog+print():void+getName():String+getHealth
():int+getLove():int+getStrain:String+Dog()-name:String-health:int-love:int-sex:StringPenguin+print():void+getName():String+getHealth
():int+getLove():int+getSex():String+Penguin()使用继承优化设计将重复代码抽取到父类中为什么使用继承?使用继承优化后:子类与父类是is-a关系,即小类是大类中的一种是继承的根底减少代码量方便修改代码
现欲定义人(Person)类和学生(Student)类,拟设立如下的属性、方法:Person-name:String-age:int-sex:String+setName(String):void+getName():String+setAge(int):void+getAge():int+setSex(String):void+getSex():String+toString():StringStudent-name:String-age:int-sex:String-school:String//新增,下同+setName(String):void+getName():String+setAge(int):void+getAge():int+setSex(String):void+getSex():String+toString():String//功能要增强+setSchool(String):void+getSchool():String 问题:Student类的很多属性、方法与Person类相同,新增的局部较少。在已声明Person类的情况下,定义Student类时是否需要将其所有属性、方法写一次?有无简便方法可用? 答复是肯定的,我们可以让Student类继承Person类。这样,Student类就可以利用Person已有属性、方法,定义时只要增加新的属性与方法即可。Person-name:String-age:int-sex:String+setName(String):void+getName():String+setAge(int):void+getAge():int+setSex(String):void+getSex():String+toString():StringStudent-school:String//新增,下同+toString():String//功能要增强+setSchool(String):void+getSchool():String
从上可知,引入“继承”机制后,可以充分利用已有的“旧类”的属性、方法,简化“新类”的设计。继承继承的概念:概念:是指在已存在的类的根底上扩展产生新的类。 已存在的类称为父类(或基类、超类),新产生的类称为子类(或派生类)。上面提到的Person类就是父类,Student类是子类。 子类继承了父类,它拥有父类的所有特性(除构造方法不被继承外),当然也可以向子类添加新的属性、方法,或改写父类原有方法,这些新变化的内容仅仅属于子类所有。意义:继承是面向对象程序设计最重要的特征之一,是实现代码重用、扩展软件功能的重要手段。 父类:更一般、更泛化 子类:更具体、更细化类的层次性: 下面以Java类库中的一些类继承关系说明如下:继承关系 一个类的子类可以是另一个类的父类,由继承关系可以形成类的层次性。继承的实现类的继承格式: class子类名extends
父类名{
//新增属性、方法,或改写父类原有方法 }例如:classBextendsA{ …… }又如:classStudentextendsPerson{ …… }
父类(或基类、超类)子类(或派生类)说明:如果没有用extends指明父类,那么默认继承Object根类,Object类是所有类的直接父类或间接父类,有关Object类的内容稍后介绍;Java只支持单一继承,不允许多重继承,即:一个子类只能有一个父类一个父类可以派生出多个子类PersonStudentSoldierOfficerGraduate采用继承机制后,简化了类的设计:只要写子类中不同父类的内容(即新增属性、方法,或改写父类原有方法)//B类继承A类classA{ //父类 intx=10; publicvoidsetX(intx){ this.x=x; } publicintgetX(){ returnx; } publicStringtoString(){ Stringinformation=""; information=information+"x="+x+"\n"; returninformation; } }classBextendsA{ //子类继承父类 inty=100; //子类新增属性 publicvoidsetY(inty){ //子类新增方法 this.y=y; } publicintgetY(){ //子类新增方法 returny; } publicStringtoString(){ //子类改写父类方法
Stringinformation=""; information=information+"x="+x+"\n";
information=information+"y="+y+"\n"; returninformation; } }publicclassInheritTest{ publicstaticvoidmain(Stringargs[]){ Aa=newA(); Bb=newB(); System.out.println(a.toString()); System.out.println(b.toString()); }}程序运行结果:x=10x=10y=100变量隐藏与方法覆盖 通过前面的介绍,我们已经知道:子类继承了父类的所有成员(变量和方法,除构造方法外)(注意:由于访问权限的限制,并不意味着父类的所有变量、方法都可以在子类中直接使用);子类还可以根据需要,增加自己的变量和方法; 除此之外,我们还可以对父类已有变量、方法进行隐藏、覆盖。Java允许在子类定义与父类同名(类型可以不同)的变量,在子类中直接使用这一变量名时,访问的是子类定义的变量,而父类同名的变量那么被隐藏起来,这称为变量的隐藏。Java还允许在子类中对父类原有的方法进行重写,以实现新的功能。 所谓方法覆盖,是指在子类中重新定义一个方法的内容,该方法与父类的某一方法在方法名、参数(包括类型、个数、次序)、返回值类型
完全相同。 当子类对象中调用这一方法时,调用的是子类改写过的方法,而父类中的原有方法被覆盖。
方法重写必须满足如下要求:重写方法和被重写方法必须具有相同的方法名;重写方法和被重写方法必须具有相同的参数列表;重写方法的返回值类型必须和被重写方法的返回值类型相同或者是其子类;重写方法的不能缩小被重写方法的访问权限。子类方法不能抛出比父类方法更多的异常。例如:在前面的B类中已改写了toString()方法的内容(即方法覆盖),使之能够输出y的值。现在,在B类中再增加一个double型的变量x,这样父类中的整型变量x就被隐藏,在toString()访问的是子类的值。 主要代码如下:publicclassCircleextendsPoint{publicintx,y,radius;
publicStringtoString(){…}
publicStringtoString(intx,inty,intradius){…}}publicclassPoint{ publicintx,y; publicStringtoString(){…} }变量的隐藏方法的覆盖方法的重载下面的例子演示了变量隐藏与方法覆盖的使用方式。//B类继承A类classA{ //父类 intx=10;//被隐藏的变量 publicvoidsetX(intx){ this.x=x; } publicintgetX(){ returnx; } publicStringtoString(){//被覆盖的方法 Stringinformation=""; information=information+"x="+x+"\n"; returninformation; } }//父类代码与前面相同,这里省略不写classBextendsA{ //子类继承父类
doublex=-12.345 //变量隐藏
inty=100; //子类新增属性 publicvoidsetY(inty){ //子类新增方法 this.y=y; } publicintgetY(){ //子类新增方法 returny; }
publicStringtoString(){ //子类改写父类方法,即方法覆盖 Stringinformation=""; information=information+"x="+x+"\n";
information=information+"y="+y+"\n"; returninformation; } }publicclassInheritTest{ publicstaticvoidmain(Stringargs[]){ Aa=newA(); Bb=newB(); System.out.println(a.toString()); System.out.println(b.toString()); }}程序运行结果:x=10x=-12.345y=100 变量隐藏容易引用变量的使用混乱,不赞成使用,而方法覆盖那么是大量使用,应掌握其内容。(问题:方法覆盖与方法重载区别是什么?)方法覆盖与方法重载的异同相同点:都要求方法同名都可以于于抽象方法和非抽象方法之间不同点:方法覆盖要求参数签名必须一致,而方法重载要求参数签名必须不一致。方法覆盖要求返回类型必须一致,而方法重载不做限制。方法覆盖只能用于子类覆盖父类的方法,方法重载用于同一个类的所有方法〔包括从父类中继承而来的方法〕。方法覆盖对方法的访问权限和抛出的异常有特殊的要求,而方法重载没有限制。父类的一个方法只能被子类覆盖一次,而一个方法所在的类中可以被屡次重载super关键字
如果要访问父类的隐藏变量、覆盖方法(需要有相应的访问权限),这该怎样办呢? 答案是使用super关键字,下面介绍该关键字的用法:Super可用来引用父类的成分,它有两种主要用法:引用父类的成员(需要相应的访问权限):
super.变量或 super.方法([参数列])在子类构造方法中调用父类的构造方法:
super([…]);//与this用法类似,应放在构造方法的第一行位置上。 还是以前面的B类继承A类为例说明如下:子类的构造顺序
下面通过一个例子来说明子类的构造顺序:classA{ publicA(){ System.out.println("调用了A类的构造方法"); }
}classBextendsA{
publicB(){ System.out.println("调用了B类的构造方法"); } }publicclassCextendsB{
publicC(){ System.out.println("调用了C类的构造方法"); } publicstaticvoidmain(Stringargs[]){ Cc=newC(); }}程序运行结果:调用了A类的构造方法调用了B类的构造方法调用了C类的构造方法 从上可以看出:在构造子类的对象时,编译器会一直上溯到最初类,执行该类构造方法,然后依次执行各子类构造函数,即以:A->B->C顺序来初始化子对象各局部。子类的构造方法:作用:用来完成对该类中的所有变量(即属性)进行初始化,子类中的变量包含从父类继承下来的变量和自己新增加的变量;分工:各类只负责在该中新增变量的初始化工作,职责清楚,不可助“类”为乐”,也即说:父类构造方法负责父类中增加变量的初绐化工作,子类构造方法负责子类中新增变量的初绐化工作;父类变量的初始化工作子类新增变量的初始化工作父类的构造方法子类的构造方法内容:在子类的构造方法中可以用super关键字来调用父类的构造方法,格式如下: 如果在子类中未显式调用父类构造方法,那么编译器会自动调用父类的默认构造方法,假假设父类没有提供默认构造方法,编译时将出错。子类构造方法([参数表]){super([父类构造方法参数]);//调用父类构造方法 其它;//对本类新增变量进行初始化或进行其它处理}执行顺序:先执行父类构造方法,再执行子类构造方法。在多层继承层时,编译器会一直上溯到最初类,再从“上”到“下”依次执行。教师演示:constructortest.java继承条件下构造方法的调用规那么如下:
如果子类的构造方法中没有通过super显式调用父类的有参构造方法,也没有通过this显式调用自身的其他构造方法,那么系统会默认先调用父类的无参构造方法。在这种情况下,写不写“super();”语句,效果是一样的。如果子类的构造方法中通过super显式调用父类的有参构造方法,那将执行父类相应构造方法,而不执行父类无参构造方法。如果子类的构造方法中通过this显式调用自身的其他构造方法,在相应构造方法中应用以上两条规那么。特别注意的是,如果存在多级继承关系,在创立一个子类对象时,以上规那么会屡次向更高一级父类应用,一直到执行顶级父类Object类的无参构造方法为止。访问权限 通过继承,子类能够获得父类中除构造方法以外的所有变量和方法,但并不意味着子类可以调用父类的这些变量、方法,这要受到访问权限的限制。//private权限类classPerson{
privateStringname=""; //私有访问权限
privateintage=0; publicPerson(Stringname,intage){ =name; this.age=age; } publicStringgetName(){ returnname; } publicintgetAge(){ returnage; }}classStudentextendsPerson{ publicStudent(Stringname,intage){ super(name,age); } publicStringtoString(){ Stringstr=""; str=str+"姓名:"+name; str=str+",年龄:"+age; returnstr; }}publicclassPrivateTest{ publicstaticvoidmain(Stringargs[]){ Studentwang=newStudent("王小丽",20); System.out.println(wang.toString()); }}22:name可以在Person中访问privatestr=str+"姓名:"+name;^F:\javaI__2006\ppt\15\code\private权限\PrivateTest.java:23:age可以在Person中访问privatestr=str+",年龄:"+age;^2错误 这是因为name、age两个变量是private权限,不允许子类直接访问。假设调用public权限的getName()、getAge(),那么问题可以迎刃而解。访问权限 Java中控制变量、方法的访问权限有四种:public:公有权限,这是访问限制最宽的修饰符,所修饰的成员可被所有类访问,实现跨类、跨包访问目的,类的成员方法一般都设置为public权限; private:私有权限,这是访问限制最严的修饰符,所修饰的成员只能在同一类中访问,不允许被其它任何类(包括子类)访问,类的成员变量一般都设置为private权限;protected:受保护权限,这是一种权限介于public、private之间的修饰符,它允许被同一包中的类和该类的子类(可位于不同包中)访问,不要误认为这一权限的保护就很严格,实际上,完全可以通过子类来到达访问父类成员的目的。较少使用。Friendly:包权限如果不加任何权限修饰符,就认为是包权限,也称为默认(缺省)或友好权限,它允许被同一包中的类访问,不允许被其它包的类访问。 根据是否在同一类、是否为子类、是否在同一个包中,可以划分为五种类型归纳如下:publicprotectedfriendly默认private同一类中是否可见是是是是对同一包中的子类是否可见是是是否对同一包中的非子类是否可见是是是否对不同包中的子类是否可见是是否否对不同包中的非子类是否可见是否否否 访问权限从高到低排序:public、protected、包的(即默认的)、private例子:Myclass:父类DerivedSamePackage:同一包中子类UnrelatedSamePackage:同一包中非子类DerivedDifferentPackage:不同包中的子类UnrelatedDifferentSamePackage:不同包中的非子类MainPack1:使用同一包中的类MainPack2:使用不同包中的类 具体代码见访问权限例子对象的类型转换对象类型的转换与根本数据类型相似,有两种方式:子类转换成父类:称为向上转型,即: 父类对象句柄=子类对象 这种转换是允许的,且自动进行。 在前面的Person、Student类的根底上,有: Personman=newStudent(“张一山”,14); 这容易理解,由于继承的子类和父类关系是“is-a”关系,也即是说,子类是父类中的一种(一个学生也是一个人)。 由于Object类是所有类的直接或间接父类,故有: Object对象名=任何类的对象对象新增的变量新增的方法继承或隐蔽的变量继承或覆盖的方法对象的上转型对象 说明:向上转型对象不能操作子类新的成员变量(失掉一局部属性),也不能使用子类新增的成员方法(失掉一局部功能)。父类转换成子类: 子类对象句柄=父类对象; //这是错误的写法,因为这种转换不会自动进行,
如果一定要将父类转换成子类,那么要强制转换,即:子类对象句柄=(子类名)父类对象; 当然这种转换要有意义,不能仅仅是为了骗守编译器,而实际读写内容错误。 例如:
Personman=newStudent(“张一山”,14); Studentst1=man; //错误
Studentst2=(Student)man; //正确final关键字阻止类的继承阻止方法的重写创立常量final关键字的用法
类不希望再被其他类继承?使用final类方法不希望被重写?使用final方法属性值不希望被修改?使用final方法publicfinalclassPenguinextendsPet{//…}最终版的类publicfinalvoidprint(){//…}最终版的方法publicclassPenguin{finalStringhome="南极";//居住地
publicvoidsetHome(Stringname){this.home=home;//错误,home不可以再次赋值}}最终版的属性值本讲小结继承的概念:引例
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 新解读《CB-T 3895-1999船用柴油机清洁度测量方法》新解读
- 新解读《CB-T 3850 - 1999船用分流式离心润滑油滤器》新解读
- 第18课 科技文化成就 课件 人教版部编八年级下册历史
- 汽车传感器与检测技术电子教案:组合式加速度传感器
- Brand KPIs for neobanking N26 in the United States-英文培训课件2025.4
- 汽车传感器与检测技术电子教案:开关式节气门位置传感器
- 单位管理量化管理制度
- 地面危险作业管理制度
- 介绍校园活动方案
- 仓库包装比赛活动方案
- 退股合同协议书照片
- 带状疱疹培训试题及答案
- 2025年湖南省常德市初中学校教学教研共同体中考二模道德与法治试卷(含答案)
- 制造业零库存管理模式
- 衢州2025年浙江衢州市柯城区属事业单位招聘30人笔试历年参考题库附带答案详解
- 用户侧储能电站项目可行性研究报告(范文)
- 2024-2025学年沪教版(五四学制)(2024)初中英语六年级下册(全册)知识点归纳
- 2025年绵阳富乐中学小升初数学、语文入学考试题
- 知识图谱与大语言模型在教育领域的应用综述
- 2025广西桂盛金融信息科技服务有限公司专业技术人员常态化招聘笔试参考题库附带答案详解
- 红色经典图书出版行业深度调研及发展战略咨询报告
评论
0/150
提交评论