《子类与继承》PPT课件.ppt

上传人:牧羊曲112 文档编号:5632323 上传时间:2023-08-04 格式:PPT 页数:76 大小:1.07MB
返回 下载 相关 举报
《子类与继承》PPT课件.ppt_第1页
第1页 / 共76页
《子类与继承》PPT课件.ppt_第2页
第2页 / 共76页
《子类与继承》PPT课件.ppt_第3页
第3页 / 共76页
《子类与继承》PPT课件.ppt_第4页
第4页 / 共76页
《子类与继承》PPT课件.ppt_第5页
第5页 / 共76页
点击查看更多>>
资源描述

《《子类与继承》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《子类与继承》PPT课件.ppt(76页珍藏版)》请在三一办公上搜索。

1、第5章子类与继承,主要内容 子类与父类 子类的继承性 子类对象的特点 成员变量的隐藏和方法重写 super关键字 final关键字 对象的上转型对象 继承与多态 abstract类与abstract方法 面向抽象编程 开-闭原则难点 成员变量的隐藏和方法重写 开-闭原则,导读,当我们准备编写一个类的时候,发现某个类已经有了我们所需要的成员变量和方法,假如我们想复用这个类中的成员变量和方法,即在所编写的类中不用声明成员变量就相当于有了这个成员变量,不用定义方法就相当于有了这个方法,那么我们可以将编写的类声明为这个类的子类。,5.1 子类与父类,在类的声明中,通过使用关键字extends来声明一个

2、类的子类,格式如下:class 子类名 extends 父类名,什么叫继承呢?所谓子类继承父类的成员变量作为自己的一个成员变量,就好像它们是在子类中直接声明一样,可以被子类中自己定义的任何实例方法操作所谓子类继承父类的方法作为子类中的一个方法,就像它们是在子类中直接定义了一样,可以被子类中自己定义的任何实例方法调用。也就是说,如果子类中定义的实例方法不能操作父类的某个成员变量或方法,那么该成员变量或方法就没有被子类继承。子类不仅可以从父类继承成员变量和方法,而且根据需要还可以声明它自己的新成员变量、定义新的方法。,5.2 子类的继承性,访问限制修饰符不仅限制了对象对自己成员变量的操作和方法的调

3、用,也限制了继承性。当子类和父类在同一个包中时,父类中的private访问权限的成员变量不会被子类继承,也就是说,子类继承父类中的除private访问权限以外的其他成员变量作为子类的成员变量;同样,子类继承父类中的除private访问权限以外的其他方法作为子类的方法。,5.2.1 子类和父类在同一包中的继承性,例5-1,public class People double height=170,weight=67.9;protected void tellHeightAndWeight()(我的体重和身高:%2.2fkg,%2.2fcmn,weight,height);,public clas

4、s Student extends People int number;void tellNumber()(我的学号是:+number);int add(int x,int y)return x+y;int sub(int x,int y)return x-y;,public class UniverStudent extends Student int multi(int x,int y)return x*y;double div(double x,double y)return x/y;,public class Example5_1 public static void main(Str

5、ing args)int x=12,y=18;Student zhang=new Student();zhang.weight=73.8;zhang.height=177;zhang.number=100101;zhang.tellHeightAndWeight();zhang.tellNumber();System.out.print(zhang会做加减:);int result=zhang.add(x,y);System.out.printf(%d+%d=%dt,x,y,result);result=zhang.sub(x,y);System.out.printf(%d-%d=%dn,x,

6、y,result);UniverStudent geng=new UniverStudent();geng.number=6609;geng.tellHeightAndWeight();geng.tellNumber();System.out.print(geng会做加减乘除:);result=geng.add(x,y);System.out.printf(%d+%d=%dt,x,y,result);result=geng.sub(x,y);System.out.printf(%d-%d=%dt,x,y,result);result=geng.multi(x,y);System.out.pri

7、ntf(%d%d=%dt,x,y,result);double re=geng.div(x,y);System.out.printf(%d%d=%fn,x,y,re);,当子类和父类不在同一个包中时,父类中的private和友好访问权限的成员变量不会被子类继承,也就是说,子类只继承父类中的protected和public访问权限的成员变量作为子类的成员变量;同样,子类只继承父类中的protected和public访问权限的方法作为子类的方法。,5.2.2 子类和父类不在同一包中的继承性,现在需要对protected总结得更全面些:A-B,B-C,C-D如果用D类在D中创建了一个对象,那么该对象

8、总是可以通过“.”运算符访问继承的或自己定义的protected变量和protected方法的,但是,如果在另外一个类中,如在Other类中用D类创建了一个对象object,该对象通过“.”运算符访问protected变量和protected方法的权限如下列(1)、(2)所述。,5.2.3 protected的进一步说明,(1)对于子类D中声明的protected成员变量和方法,如果object要访问这些protected成员变量和方法,只要Other类和D类在同一个包中就可以了。(2)如果子类D的对象的protected成员变量或protected方法是从父类继承的,那么就要一直追溯到该pr

9、otected成员变量或方法的“祖先”类,即A类,如果Other类和A类在同一个包中,那么object对象能访问继承的protected变量和protected方法。,如果一个类是另一个类的子类,那么UML通过使用一个实线连接两个类的UML图来表示二者之间的继承关系,实线的起始端是子类的UML图,终点端是父类的UML图,但终点端使用一个空心的三角形表示实线的结束。,5.2.4 继承关系(Generalization)的UML图,instanceof是双目运算符,其左面的操作元是对象,右面的操作元是类,当左面的操作元是右面的类或子类所创建的对象时,instanceof运算的结果是true,否则是

10、false。,5.2.5 关于instanceof运算符,当用子类的构造方法创建一个子类的对象时,不仅子类中声明的成员变量被分配了内存,而且父类的成员变量也都分配了内存空间,但只将其中一部分(子类继承的那部分)作为分配给子类对象的变量。也就是说,父类中的private成员变量尽管分配了内存空间,也不作为子类对象的变量,即子类不继承父类的私有成员变量。,5.3 子类对象的特点,同样,如果子类和父类不在同一包中,尽管父类的友好成员变量分配了内存空间,但也不作为子类的成员变量,即如果子类和父类不在同一包中,子类不继承父类的友好成员变量。,例5-2,public class A private int

11、 x;public void setX(int x)this.x=x;public int getX()return x;,public class B extends A double y=12;public void setY(int y)/this.y=y+x;非法,子类没有继承x public double getY()return y;,public class Example5_2 public static void main(String args)B b=new B();b.setX(888);(子类对象未继承的x的值是:+b.getX();b.y=12.678;(子类对象的

12、实例变量y的值是:+b.getY();,5.4.1 成员变量的隐藏子类对象以及子类自己声明定义的方法操作与父类同名的成员变量是指子类重新声明定义的这个成员变量。需要注意的是,子类对象仍然可以调用从父类继承的方法操作隐藏的成员变量。,5.4 成员变量的隐藏和方法重写,例5-3,public class Goods public double weight;public void oldSetWeight(double w)weight=w;System.out.println(double型的weight=+weight);public double oldGetPrice()double pr

13、ice=weight*10;return price;,public class CheapGoods extends Goods public int weight;public void newSetWeight(int w)weight=w;System.out.println(int型的weight=+weight);public double newGetPrice()double price=weight*10;return price;,public class Example5_3 public static void main(String args)CheapGoods c

14、heapGoods=new CheapGoods();cheapGoods.weight=198.98;cheapGoods.newSetWeight(198);(对象cheapGoods的weight的值是:+cheapGoods.weight);System.out.println(cheapGoods用子类新增的优惠方法计算价格:+cheapGoods.newGetPrice();cheapGoods.oldSetWeight(198.987);/子类对象调用继承的方法操作隐藏的double型变量weight System.out.println(cheapGoods使用继承的方法(无优

15、惠)计算价格:+cheapGoods.oldGetPrice();,1重写的语法规则方法重写是指:子类中定义一个方法,这个方法的类型和父类的方法的类型一致或者是父类的方法的类型的子类型(所谓子类型是指:如果父类的方法的类型是“类”,那么允许子类的重写方法的类型是“子类”),并且这个方法的名字、参数个数、参数的类型和父类的方法完全相同。子类如此定义的方法称作子类重写的方法(不属于新增的方法)。,5.4.2 方法重写(Override),2重写的目的子类通过方法的重写可以隐藏继承的方法,子类通过方法的重写可以把父类的状态和行为改变为自身的状态和行为。如果父类的方法f可以被子类继承,子类就有权利重写

16、f,一旦子类重写了父类的方法f,就隐藏了继承的方法f,那么子类对象调用方法f调用的一定是重写方法f。重写方法既可以操作继承的成员变量、继承的方法,也可以操作子类新声明的成员变量、新定义的其他方法,但无法操作被子类隐藏的成员变量和方法。如果子类想使用被隐藏的方法或成员变量,必须使用关键字super,例5-4,public class University void enterRule(double math,double english,double chinese)double total=math+english+chinese;if(total=200)(考分+total+达到大学最低录取

17、线);else(考分+total+未达到大学最低录取线);,public class ImportantUniversity extends University void enterRule(double math,double english,double chinese)double total=math+english+chinese;if(total=245)(考分+total+达到重点大学最低录取线);else(考分+total+未达到重点大学最低录取线);,public class Example5_4 public static void main(String args)do

18、uble math=64,english=76.5,chinese=66;ImportantUniversity univer=new ImportantUniversity();univer.enterRule(math,english,chinese);/调用重写的方法 math=89;english=80;chinese=86;univer=new ImportantUniversity();univer.enterRule(math,english,chinese);/调用重写的方法,class A float computer(float x,float y)return x+y;p

19、ublic int g(int x,int y)return x+y;class B extends A float computer(float x,float y)return x*y;public class Example5_5 public static void main(String args)B b=new B();double result=puter(8,9);/b调用重写的方法(调用重写方法得到的结果:+result);int m=b.g(12,8);/b调用继承的方法(调用继承方法得到的结果:+m);,例5-5,在JDK 1.5版本之后,允许重写方法的类型可以是父类方法

20、的类型的子类型,即不必完全一致(JDK 1.5版本之前要求必须一致),也就是说,如果父类的方法的类型是“类”,重写方法的类型可以是“子类”。,3JDK 1.5对重写的改进,例5-6,public class HomeEletricity int weight;public void setWeight(int w)weight=w;public void showMess()(我是家用电器);,public class Television extends HomeEletricity public void showMess()(我是电视机,重量是+weight+kg);public cla

21、ss Icebox extends HomeEletricity public void showMess()(我是冰箱,重量是+weight+kg);,class Factory public HomeEletricity make()/方法的类型是HomeEletricity类 HomeEletricity machine=new HomeEletricity();return machine;class TVFactory extends Factory public Television make()/重写方法的类型是HomeEletricity类的子类:Television Tele

22、vision tv=new Television();tv.setWeight(21);return tv;class IceboxFactory extends Factory public Icebox make()/重写方法的类型是HomeEletricity类的子类:Icebox Icebox icebox=new Icebox();icebox.setWeight(67);return icebox;public class Example5_6 public static void main(String args)TVFactory factory1=new TVFactory(

23、);Television tv=factory1.make();/factory1调用重写的方法 tv.showMess();IceboxFactory factory2=new IceboxFactory();Icebox icebox=factory2.make();/factory2调用重写的方法 icebox.showMess();,重写父类的方法时,不可以降低方法的访问权限。下面的代码中,子类重写父类的方法f,该方法在父类中的访问权限是protected级别,子类重写时不允许级别低于protected,4重写的注意事项,class Aprotected float f(float x

24、,float y)return x-y;class B extends Afloat f(float x,float y)return x+y;,5.5.1 用super操作被隐藏的成员变量和方法子类一旦隐藏了继承的成员变量,那么子类创建的对象就不再拥有该变量,该变量将归关键字super所有,同样子类一旦隐藏了继承的方法,那么子类创建的对象就不能调用被隐藏的方法,该方法的调用由关键字super负责。因此,如果在子类中想使用被子类隐藏的成员变量或方法就需要使用关键字super。,5.5 super关键字,例5-7,public class Bank int savedMoney;int year

25、;double interest;public double computerInterest()interest=year*0.035*savedMoney;System.out.printf(%d元存在银行%d年的利息:%f元n,savedMoney,year,interest);return interest;,public class ConstructionBank extends Bank double year;public double computerInterest()super.year=(int)year;double remainNumber=year-(int)ye

26、ar;int day=(int)(remainNumber*1000);interest=puterInterest()+day*0.0001*savedMoney;System.out.printf(%d元存在建设银行%d年零%d天的利息:%f元n,savedMoney,super.year,day,interest);return interest;,public class BankOfDalian extends Bank double year;public double computerInterest()super.year=(int)year;double remainNumb

27、er=year-(int)year;int day=(int)(remainNumber*1000);interest=puterInterest()+day*0.00012*savedMoney;System.out.printf(%d元存在大连银行%d年零%d天的利息:%f元n,savedMoney,super.year,day,interest);return interest;,public class Example5_7 public static void main(String args)int amount=5000;ConstructionBank bank1=new Co

28、nstructionBank();bank1.savedMoney=amount;bank1.year=5.216;double interest1=puterInterest();BankOfDalian bank2=new BankOfDalian();bank2.savedMoney=amount;bank2.year=5.216;double interest2=puterInterest();(两个银行利息相差%f元n,interest2-interest1);,当用子类的构造方法创建一个子类的对象时,子类的构造方法总是先调用父类的某个构造方法,也就是说,如果子类的构造方法没有明显地

29、指明使用父类的哪个构造方法,子类就调用父类的不带参数的构造方法,即如果在子类的构造方法中,没有明显地写出super关键字来调用父类的某个构造方法,那么默认地有:super();子类不继承父类的构造方法,因此,子类在其构造方法中需使用super来调用父类的构造方法,而且super必须是子类构造方法中的头一条语句。,5.5.2 使用super调用父类的构造方法,例5-8,public class Card String title;Card()title=新年快乐!;Card(String title)this.title=title;public String getTitle()return

30、title;,public class ChristmasCard extends Card String content;/子类新增的content ChristmasCard(String title,String content)super(title);/调用父类的构造方法,即执行Card(title)this.content=content;public void showCard()(*+getTitle()+*);System.out.printf(%s,content);,public class Example5_8 public static void main(Strin

31、g args)String title=Happy New Year To You;String content=t牛年耕耘nt谷穗满仓nt出生牛犊nt喜迎虎年n;ChristmasCard card=new ChristmasCard(title,content);card.showCard();,final关键字可以修饰类、成员变量和方法中的局部变量。,5.6 final关键字,可以使用final将类声明为final类。final类不能被继承,即不能有子类。如:final class A A就是一个final类,将不允许任何类声明成A的子类。有时候是出于安全性的考虑,将一些类修饰为fina

32、l类。例如,Java提供的String类,它对于编译器和解释器的正常运行有很重要的作用,对它不能轻易改变,它被修饰为final类。,5.6.1 final类,如果用final修饰父类中的一个方法,那么这个方法不允许子类重写,也就是说,不允许子类隐藏可以继承的final方法(老老实实继承,不许做任何篡改)。,5.6.2 final方法,如果成员变量或局部变量被修饰为final,那么它就是常量。常量在声明时没有默认值,所以在声明常量时必须指定该常量的值,而且不能再发生变化。,5.6.3 常量,class A final double PI=3.1415926;/PI是常量 public doubl

33、e getArea(final double r)return PI*r*r;public final void speak()(您好,Hows everything here?);public class Example5_9 public static void main(String args)A a=new A();(面积:+a.getArea(100);a.speak();,假设,A类是B类的父类,当用子类创建一个对象,并把这个对象的引用放到父类的对象中时,如:A a;a=new B();或A a;B b=new B();a=b;这时,称对象a是对象b的上转型对象(就像说:“美国人是

34、人”)。对象的上转型对象的实体是子类负责创建的,但上转型对象会失去原对象的一些属性和功能(上转型对象相当于子类对象的一个“简化”对象)。,5.7 对象的上转型对象,(1)上转型对象不能操作子类新增的成员变量(失掉了这部分属性);不能调用子类新增的方法(失掉了一些功能)。(2)上转型对象可以访问子类继承或隐藏的成员变量,也可以调用子类继承的方法或子类重写的实例方法。上转型对象操作子类继承的方法或子类重写的实例方法,其作用等价于子类对象去调用这些方法。因此,如果子类重写了父类的某个实例方法后,当对象的上转型对象调用这个实例方法时一定是调用了子类重写的实例方法。,上转型对象具有如下特点(重要),例5

35、-10,public class People int height;double weight;void showBodyMess()(*n);void mustDoingThing()(吃饭、睡觉.饮水);,public class American extends People void showBodyMess()System.out.println(bodyHeight:+height+cm+bodyWeight:+weight+kg);void speakEnglish()System.out.println(I am Amerian);,public class Chinese

36、extends People void showBodyMess()(身高:%5dcmt体重:%3.2fkgn,height,weight);void speakChinese()(我是中国人);,public class Example5_10 public static void main(String args)People people=null;American Johnson=new American();people=Johnson;/people是Johnson对象的上转型对象。people.height=187;/同于Johnson.height=187 people.wei

37、ght=78.67;people.showBodyMess();/等同于Johnson调用重写的showBodyMess()方法/people.speakEnglish();/非法,因为speakEnglish()是子类新增的方法 people.mustDoingThing();Chinese zhang=new Chinese();people=zhang;/people是zhang对象的上转型对象。people.height=177;/同于zhang.height=187 people.weight=68.59;people.showBodyMess();/等同于Johnson调用重写的s

38、howBodyMess()方法/people.speakChinese();/非法,因为speakChinese()是子类新增的方法 people.mustDoingThing();zhang=(Chinese)people;zhang.speakChinese();,当一个类有很多子类时,并且这些子类都重写了父类中的某个实例方法,那么当我们把子类创建的对象的引用放到一个父类的对象中时,就得到了该对象的一个上转型对象,那么这个上转型对象在调用这个实例方法时就可能具有多种形态,因为不同的子类在重写父类的实例方法时可能产生不同的行为。多态性就是指父类的某个实例方法被其子类重写时,可以各自产生自己的

39、功能行为。,5.8 继承与多态,5-11,class EspecialCar void cautionSound()class PoliceCar extends EspecialCar void cautionSound()System.out.println(zhua.zhua.zhua.);class AmbulanceCar extends EspecialCar void cautionSound()System.out.println(jiu.jiu.jiu.);class FireCar extends EspecialCar void cautionSound()System.

40、out.println(huo.huo.huo.);public class Example5_11 public static void main(String args)EspecialCar car=new PoliceCar();/car是警车的上转型对象 car.cautionSound();car=new AmbulanceCar();/car是救护车的上转型对象 car.cautionSound();car=new FireCar();/car是消防车的上转型对象 car.cautionSound();,用关键字abstract修饰的类称为abstract类(抽象类)。如:abs

41、tract class A 用关键字abstract修饰的方法称为abstract方法(抽象方法),对于abstract方法,只允许声明,不允许实现,而且不允许使用final和abstract同时修饰一个方法,5.9 abstract类和abstract方法,和普通的类相比,abstract类可以有abstract方法(抽象方法)也可以有非abstract方法。,1abstract类中可以有abstract方法,abstract class Aabstract int min(int x,int y);int max(int x,int y)return xy?x:y;,对于abstract类

42、,我们不能使用new运算符创建该类的对象。如果一个非抽象类是某个抽象类的子类,那么它必须重写父类的抽象方法,给出方法体,这就是为什么不允许使用final和abstract同时修饰一个方法的原因。注:abstract类也可以没有abstract方法。注:如果一个abstract类是abstract类的子类,它可以重写父类的abstract方法,也可以继承这个abstract方法。,2abstract类不能用new运算创建对象,abstract class A abstract int sum(int x,int y);int sub(int x,int y)return x-y;class B

43、extends A int sum(int x,int y)/子类必须重写父类的sum方法 return x+y;public class Example5_12 public static void main(String args)B b=new B();int sum=b.sum(30,20);/调用重写的方法 int sub=b.sub(30,20);/调用继承的方法 System.out.println(sum=+sum);/输出结果为sum=50 System.out.println(sum=+sub);/输出结果为sum=10,在设计程序时,经常会使用abstract类,其原因是

44、,abstract类只关心操作,但不关心这些操作具体实现的细节,可以使程序的设计者把主要精力放在程序的设计上,而不必拘泥于细节的实现(将这些细节留给子类的设计者),即避免设计者把大量的时间和精力花费在具体的算法上。在设计一个程序时,可以通过在abstract类中声明若干个abstract方法,表明这些方法在整个系统设计中的重要性,方法体的内容细节由它的非abstract子类去完成。,5.10 面向抽象编程,使用多态进行程序设计的核心技术之一是使用上转型对象,即将abstract类声明对象作为其子类的上转型对象,那么这个上转型对象就可以调用子类重写的方法。所谓面向抽象编程,是指当设计一个类时,不

45、让该类面向具体的类,而是面向抽象类,即所设计类中的重要数据是抽象类声明的对象,而不是具体类声明的对象。,小例题,public class Circledouble r;Circle(double r)this.r=r;public double getArea()return 3.14*r*r;,public class PillarCircle bottom;dobule height;Pillar(Circle bottom,double height)this.bottom=bottom;this.height=height;public double getVolume()return

46、 bottom.getArea()*height;,分析,当用户要把柱体的底改变的时候,则Pillar类无法适应该需求可以抽象出一个抽象的图像类public abstract class Geometrypublic abstract double getArea();下面重写Pillar类和Circle 类,public class PillarGeometry bottom;dobule height;Pillar(Geometry bottom,double height)this.bottom=bottom;this.height=height;public double getVol

47、ume()return bottom.getArea()*height;,public class Circle extends Geometrydouble r;Circle(double r)this.r=r;public double getArea()return 3.14*r*r;,扩展了一个长方形类,public class Rectangle extends Geometrydouble a,b;Rectangle(double a,double b)this.a=a;this.b=b;public double getArea()return a*b;,public class

48、 Application Pillar pillar;Geometry bottom;bottom=new Rectangle(12,22);pillar=new Pillar(bottom,58);(矩形圆柱体的体积是:+pillar.getVolume();bottom=new Circle(10);pillar=new Pillar(bottom,58);(圆形底圆柱体的体积是:+pillar.getVolume();,所谓“开-闭原则”(Open-Closed Principle)就是让设计的系统应当对扩展开放,对修改关闭。实际上这句话的本质是指当系统中增加新的模块时,不需要修改现有的

49、模块。在设计系统时,应当首先考虑到用户需求的变化,将应对用户变化的部分设计为对扩展开放,而设计的核心部分是经过精心考虑之后确定下来的基本结构,这部分应当是对修改关闭的,,5.11 开-闭原则,例5-13,public abstract class Animal public abstract void cry();public abstract String getAnimalName();public class Simulator public void playSound(Animal animal)(现在播放+animal.getAnimalName()+类的声音:);animal.c

50、ry();,public class Dog extends Animal public void cry()(汪汪.汪汪);public String getAnimalName()return 狗;public class Cat extends Animal public void cry()(喵喵.喵喵);public String getAnimalName()return 猫;,public class Application public static void main(String args)Simulator simulator=new Simulator();simula

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号