资源描述
1/39,继承,2,目录,1 类的继承2 终结类与终结方法3 抽象类4 类的组合,Java类的定义public abstract|final class 类名extends 父类名 implements 接口名 成员变量(域)定义 成员函数(方法)定义,3/39,4,1 类的继承,类的继承一种由已有的类创建新类的机制,是面向对象程序设计的基石之一通过继承,可以根据已有类来定义新类,新类拥有已有类的所有功能Java只支持类的单继承,每个子类只能有一个直接父类父类是所有子类的公共属性及方法的集合,子类则是父类的特殊化继承机制可以提高程序的抽象程度,提高代码的可重用性,5,基类(base class)也称超类(superclass)是被直接或间接继承的类派生类(derived-class)也称子类 (subclass)继承其他类而得到的类继承所有祖先的状态和行为派生类可以增加变量和方法派生类也可以覆盖(override)继承的方法,1 类的继承,1.1 继承的概念基类和派生类,6,子类对象与父类对象存在“IS A”(或“is a kind of”)的关系,1 类的继承,1.1 继承的概念is_a关系,7,动物类层次举例,一般,具体,动物,蛇,蜥蜴,鲸,爬行动物,哺乳动物,狗,巨蜥,壁虎,壁虎,是一种,蜥蜴,爬行,动物是,动物的,一种,1 类的继承,1.1 继承的概念图,8,举例,1 类的继承,1.1 继承的概念又一个例子,9,10,派生类产生的对象从外部来看,它应该包括与基类相同的接口可以具有更多的方法和数据成员其内包含着一个基类类型的子对象,1 类的继承,1.1 继承的概念派生类对象,11,1.2 继承的语法,继承的语法class childClass extends parentClass /类体,类的继承,1 类的继承,12,在一个公司中,有普通员工(Employees)及管理人员(Magagers)两类人员职员对象(Employees)可能有的属性信息包括员工号(employeeNumber)姓名(name)地址(address)电话号码(phoneNumber)管理人员(Managers)除具有普通员工的属性外,还可能具有下面的属性职责(responsibilities)所管理的职员(listOfEmployees),1 类的继承,1.2 继承的语法(续)例,13,Employee与Manager的类图,1 类的继承,1.2 继承的语法(续)例,14,/父类Employeeclass Employee int employeeNumbe ; String name, address, phoneNumber ;/子类Managerclass Manager extends Employee /子类增加的数据成员 String responsibilities, listOfEmployees;,1 类的继承,1.2 继承的语法(续)例,15,设有三个类:Person, Employee, Manager。其类层次如图:,1.2 继承的语法(续)例,16,1.2 继承的语法(续)例,17,1.2 继承的语法(续)例,18,1.2 继承的语法(续)例,19,1 类的继承,1.2 继承的语法(续),20,21,22,1 类的继承,通过继承,可以根据已有类来定义新类,新类拥有已有类的所有功能父类是所有子类的公共属性及方法的集合,子类则是父类的特殊化继承机制可以提高程序的抽象程度,提高代码的可重用性,23,子类不能直接访问父类中的私有属性及方法可使用公有(及保护)方法进行访问,1 类的继承,1.2 继承的语法(续)例,24,public class B public int a = 10; private int b = 20; protected int c = 30; public int getB() return b; public class A extends B public int d; public void tryVariables() System.out.println(a); /允许 System.out.println(b); /不允许 System.out.println(getB(); /允许 System.out.println(c); /允许 ,1 类的继承,1.2 继承的语法(续),25,1.3 隐藏和覆盖,扩展类继承已有的属性和方法改写已有的属性和方法改写已有的属性:隐藏改写已有的方法:覆盖,1 类的继承,26,属性的隐藏子类中声明了与父类中相同的成员变量名,则从父类继承的变量将被隐藏子类拥有了两个相同名字的变量,一个继承自父类,另一个由自己声明当子类执行继承自父类的操作时,处理的是继承自父类的变量,而当子类执行它自己声明的方法时,所操作的就是它自己声明的变量,class Parent int aNumber;,class Child extends Parent float aNumber;,1 类的继承,1.3 隐藏和覆盖(续)属性的隐藏,27,如何访问被隐藏的父类属性调用从父类继承的方法,则操作的是从父类继承的属性调用被隐藏的属性super.属性,1 类的继承,1.3 隐藏和覆盖(续)访问被隐藏的父类属性,28,class A1 int x = 2; public void setx(int i) x = i; void printa() System.out.println(x); class B1 extends A1 int x=100; void printb() super.x = super.x +10 ; System.out.println(super.x= + super.x + x= + x); ,运行结果:4super.x= 12 x= 10012super.x= 16 x= 100164,public class Exam4_4Test public static void main(String args) A1 a1 = new A1(); a1.setx(4); a1.printa(); B1 b1 = new B1(); b1.printb(); b1.printa(); b1.setx(6); / 将继承x值设置为6 b1.printb(); b1.printa(); a1.printa(); ,1 类的继承,1.3 隐藏和覆盖(续)例属性的隐藏举例,29,30,31,32,33,34,子类不能继承父类中的静态属性,但可以对父类中的静态属性进行操作。如在上面的例子中,将“int x = 2;”改为“static int x = 2;”,再编译及运行程序,会得到下面的结果4super.x= 14 x= 10014super.x= 16 x= 1001616在上面的结果中,第一行及最后一行都是语句“a1.printa();”输出的结果,显然类中的printb()方法修改的是类中的静态属性x,1 类的继承,1.3 隐藏和覆盖(续)例 操作父类静态属性举例,35,36,1.3 隐藏和覆盖,扩展类继承已有的属性和方法改写已有的属性和方法改写已有的属性:隐藏改写已有的方法:覆盖,1 类的继承,37,方法覆盖覆盖方法的返回类型,方法名称,参数的个数及类型必须和被覆盖的方法一摸一样覆盖方法的访问权限可以比被覆盖的宽松,但是不能更为严格,1 类的继承,1.3 隐藏和覆盖(续)方法覆盖,38,方法覆盖的应用场合子类中实现与父类相同的功能,但采用不同的算法或公式 在名字相同的方法中,要做比父类更多的事情 在子类中需要取消从父类继承的方法,1 类的继承,1.3 隐藏和覆盖(续)方法覆盖的应用场合,39,必须覆盖的方法派生类必须覆盖基类中的抽象的方法,否则派生类自身也成为抽象类.不能覆盖的方法基类中声明为final的终结方法基类中声明为static 的静态方法调用被覆盖的方法super.overriddenMethodName();,1 类的继承,1.3 隐藏和覆盖(续)方法覆盖的注意事项,40,1.4 有继承时的构造方法,有继承时的构造方法遵循以下的原则子类不能从父类继承构造方法好的程序设计方法是在子类的构造方法中调用某一个父类构造方法,调用语句必须出现在子类构造方法的第一行,可使用super关键字如子类构造方法的声明中没有明确调用父类构造方法,则系统在执行子类的构造方法时会自动调用父类的默认构造方法(即无参的构造方法),1 类的继承,41,public class Person protected String name, phoneNumber, address; public Person() this(, , ); public Person(String aName, String aPhoneNumber, String anAddress) name = aName; phoneNumber = aPhoneNumber; address = anAddress; ,1 类的继承,1.4 有继承时的构造方法(续)例,42,public class Employee extends Person protected int employeeNumber; protected String workPhoneNumber; public Employee() /此处隐含调用构造方法 Person() this(0, ); public Employee(int aNumber, String aPhoneNumber) /此处隐含调用构造方法 Person() employeeNumber = aNumber; workPhoneNumber = aPhoneNumber; ,1 类的继承,1.4 有继承时的构造方法(续)例,43,public class Professor extends Employee protected String research; public Professor() super(); research = ; public Professor(int aNumber, String aPhoneNumber, String aResearch) super(aNumber, aPhoneNumber); research = aResearch; ,1 类的继承,1.4 有继承时的构造方法(续)例,44,目录,1 类的继承2 终结类与终结方法3 抽象类4 类的组合,Java类的定义public abstract|final class 类名extends 父类名 implements 接口名 成员变量(域)定义 成员函数(方法)定义,45/39,46,2 终结类与终结方法,终结类与终结方法被final修饰符修饰的类和方法终结类不能被继承终结方法不能被当前类的子类重写,47,终结类的特点不能有派生类终结类存在的理由安全: 黑客用来搅乱系统的一个手法是建立一个类的派生类,然后用他们的类代替原来的类设计: 你认为你的类是最好的或从概念上你的类不应该有任何派生类,2 终结类与终结方法,2.1 终结类,48,声明ChessAlgorithm 类为final 类final class ChessAlgorithm . . . 如果写下如下程序:class BetterChessAlgorithm extends ChessAlgorithm 编译器将显示一个错误Chess.java:6: Cant subclass final classes: class ChessAlgorithmclass BetterChessAlgorithm extends ChessAlgorithm 1 error,2 终结类与终结方法,2.1 终结类(续)一个例子,49,终结方法的特点不能被派生类覆盖终结方法存在的理由对于一些比较重要且不希望子类进行更改的方法,可以声明为终结方法。可防止子类对父类关键方法的错误重写,增加了代码的安全性和正确性提高运行效率。通常,当java运行环境(如java解释器)运行方法时,它将首先在当前类中查找该方法,接下来在其超类中查找,并一直沿类层次向上查找,直到找到该方法为止,2 终结类与终结方法,2.2 终结方法,50,final 方法举例class Parent public Parent() /构造方法 final int getPI() return Math.PI; /终结方法说明getPI()是用final修饰符声明的终结方法,不能在子类中对该方法进行重载,因而如下声明是错的Class Child extends Parent public Child() /构造方法 int getPI() return 3.14; /重写父类中的终结方法,不允许,2 终结类与终结方法,2.2 终结方法(续)例,51,目录,1 类的继承2 终结类与终结方法3 抽象类4 类的组合,Java类的定义public abstract|final class 类名extends 父类名 implements 接口名 成员变量(域)定义 成员函数(方法)定义,52/39,53,3 抽象类,抽象类代表一个抽象概念的类没有具体实例对象的类,不能使用new方法进行实例化类前需加修饰符abstract可包含常规类能够包含的任何东西,例如构造方法,非抽象方法也可包含抽象方法,这种方法只有方法的声明,而没有方法的实现,54,存在意义抽象类是类层次中较高层次的概括,抽象类的作用是让其他类来继承它的抽象化的特征抽象类中可以包括被它的所有子类共享的公共行为抽象类可以包括被它的所有子类共享的公共属性在程序中不能用抽象类作为模板来创建对象;在用户生成实例时强迫用户生成更具体的实例,保证代码的安全性,3 抽象类(续)存在意义,55,将所有图形的公共属性及方法抽象到抽象类Shape。再将2D及3D对象的特性分别抽取出来,形成两个抽象类TwoDimensionalShape及ThreeDimensionalShape2D图形包括Circles、Triangles、Rectangles和Squares3D图形包括Cube、Sphere、或Tetrahedron在UML中,抽象类的类名为斜体,以与具体类相区别,3 抽象类(续)几何形状的例子,56,57,前例中,如果在应用系统中涉及到的人员只包括:Customers,Employees 及 Managers。则Person 类的子类对象覆盖了应用中的对象,可以将Person 类声明为抽象类,3 抽象类(续)人员的例子,58,3.1 抽象类的声明,抽象类声明的语法形式为abstract class Number . . .如果写: new Number();编译器将显示错误,3 抽象类,59,3.2 抽象方法,抽象方法声明的语法形式为public abstract (.);仅有方法头,而没有方法体和操作实现具体实现由当前类的不同子类在它们各自的类声明中完成抽象类可以包含抽象方法,3 抽象类,60,需注意的问题一个抽象类的子类如果不是抽象类,则它必须为父类中的所有抽象方法书写方法体,即重写父类中的所有抽象方法只有抽象类才能具有抽象方法,即如果一个类中含有抽象方法,则必须将这个类声明为抽象类除了抽象方法,抽象类中还可以包括非抽象方法,3 抽象类,3.2 抽象方法(续)需注意的问题,61,抽象方法的优点隐藏具体的细节信息,所有的子类使用的都是相同的方法头,其中包含了调用该方法时需要了解的全部信息强迫子类完成指定的行为,规定其子类需要用到的“标准”行为,3 抽象类,3.2 抽象方法(续)抽象方法的优点,62,各种图形都需要实现绘图方法,可在它们的抽象父类中声明一个draw抽象方法abstract class GraphicObject int x, y; void moveTo(int newX, int newY) . . . abstract void draw();,3 抽象类,3.2 抽象方法(续)一个绘图的例子,63,然后在每一个子类中重写draw方法,例如:class Circle extends GraphicObject void draw() . . . class Rectangle extends GraphicObject void draw() . . . ,3 抽象类,3.2 抽象方法(续)一个绘图的例子,64,目录,1 类的继承2 终结类与终结方法3 抽象类4 类的组合,65,66,4.1 组合的语法,组合的语法很简单,只要把已存在类的对象放到新类中即可可以使用“has a”语句来描述这种关系例如,考虑Kitchen类提供烹饪和冷藏食品的功能,很自然的说“my kitchen has a cooker/refrigerator”。所以,可简单的把对象myCooker和myRefrigerator放在类Kitchen中。格式如下class Cooker / 类的语句 class Refrigerator / 类的语句class Kitchen Cooker myCooker; Refrigerator myRefrigerator;,4 类的组合,67,一条线段包含两个端点public class Point /点类 private int x, y; /coordinate public Point(int x, int y) this.x = x; this.y = y; public int GetX() return x; public int GetY() return y; ,4类的组合,4.1 组合的语法例,68,class Line /线段类 private Point p1,p2; / 两端点 Line(Point a, Point b) p1 = new Point(a.GetX(),a.GetY(); p2 = new Point(b.GetX(),b.GetY(); public double Length() return Math.sqrt(Math.pow(p2.GetX()-p1.GetX(),2) + Math.pow(p2.GetY()-p1.GetY(),2); ,4 类的组合,4.1 组合的语法例,69,car(汽车)对象是一个很好的例子,由于汽车的装配是故障分析时需要考虑的一项因素,所以有助于客户程序员理解如何使用类,而且类创建者的编程复杂程度也会大幅度降低class Engine /发动机类public void start() public void rev() public void stop() ,4 类的组合,4.1 组合与继承的比较(续)Car的例子,70,class Wheel /车轮类 public void inflate(int psi) class Window /车窗类public void rollup() public void rolldown() class Door /车门类public Window window = new Window();public void open() public void close() ,4 类的组合,4.1 组合与继承的比较(续)Car的例子,71,public class Car public Engine engine = new Engine(); public Wheel wheel = new Wheel4;public Door left = new Door(),right = new Door(); public Car() for(int i = 0; i 4; i+) wheeli = new Wheel();public static void main(String args) Car car = new Car();car.left.window.rollup();car.wheel0.inflate(72);,4 类的组合,4.1 组合与继承的比较(续)Car的例子,72,许多时候都要求将组合与继承两种技术结合起来使用,创建一个更复杂的类,4 类的组合,4.1 组合与继承的结合,73,组合与继承举例class Plate /声明盘子public Plate(int i) System.out.println(Plate constructor);class DinnerPlate extends Plate /声明餐盘为盘子的子类public DinnerPlate(int i) super(i);System.out.println(DinnerPlate constructor);,4 类的组合,4.1 组合与继承的结合(续)例,74,class Utensil /声明器具Utensil(int i) System.out.println(Utensil constructor);class Spoon extends Utensil /声明勺子为器具的子类public Spoon(int i) super(i);System.out.println(Spoon constructor);,4 类的组合,4.1 组合与继承的结合(续)例,75,class Fork extends Utensil /声明餐叉为器具的子类public Fork(int i) super(i);System.out.println(Fork constructor);class Knife extends Utensil /声明餐刀为器具的子类public Knife(int i) super(i);System.out.println(Knife constructor);,4 类的组合,4.1 组合与继承的结合(续)例,76,class Custom / 声明做某事的习惯public Custom(int i) System.out.println(Custom constructor);public class PlaceSetting extends Custom /声明餐桌的布置 Spoon sp; Fork frk; Knife kn; DinnerPlate pl;public PlaceSetting(int i) super(i + 1);sp = new Spoon(i + 2);frk = new Fork(i + 3);kn = new Knife(i + 4);pl = new DinnerPlate(i + 5);System.out.println(PlaceSetting constructor);public static void main(String args) PlaceSetting x = new PlaceSetting(9);,4 类的组合,4.1 组合与继承的结合(续)例,77,运行结果Custom constructorUtensil constructorSpoon constructorUtensil constructorFork constructorUtensil constructorKnife constructorPlate constructorDinnerPlate constructorPlaceSetting constructor,4 类的组合,4.1 组合与继承的结合(续)例运行结果,
展开阅读全文