第5章 继承、接口与包 面向对象的程序设计与JAVA娄不夜 王利 编著主讲:胡传福E-mail:hucf@dgut.edu.cn 继承 对一个已定义的类进行扩展、派生出一个新类.新类称为被扩展类的直接子类.被扩展类称为新类的直接超类(或父类).子类继承父类的成员变量和方法,并可以定义自己的成员变量和方法. extends子句 语法:[<修饰符>]class<子类名>extends<直接超类名>{[<定义成员变量>…][<定义构造方法>…][<初始化块>…][<方法定义>…]} 类成员 一个类除了自己在类体中定义的成员之外,还能够从其直接超类和直接超接口中继承一些成员在类体中定义的成员从它的直接超接口继承的成员.从它的直接超类继承的成员 类的成员及其访问关系 is-a关系 可以将子类看做超类对象,因为子类一般比超类有更多的成员(why?)可以将一个子类对象赋值给一个超类类型变量.不能将一个超类类型对象赋值给一个子类类型对象. 成员变量隐藏 在子类中定义一个与直接超 类中的某个成员变量同名的成员变量,从而使直接超类中的那个成员变量不能被子类继承.简单变量名访问只能是访问自己定义的成员变量.子类代码可以用下列方法访问隐藏的变量:super.<变量名>((<超类名>)<子类实例引用>).<变量名><超类名>.<变量名> 成员变量隐藏 关键字super和this都表示当前对象的引用.this的编译期类型为方法体所在的类.super的编译期类型为当前类的直接超类.super和this都应该在类的实例方法中使用.(why?) 变量隐藏示意图 方法覆盖 方法覆盖是指在子类中定义了一个与直接超类中的某个实例方法具有相同方法签名的实例方法,从而使直接超 类中的那个方法不能被子类继承.一个正确的方法覆盖需要满足以下要求:覆盖方法与被覆盖方法的返回类型要相同.覆盖方法的访问级别不能低于被覆盖方法的访问级别.覆盖方法不能比被覆盖方法抛出更多的受检查例外例外的类型. 方法覆盖(续…) 子类中访问直接超类中被覆盖的方法:super.<方法名>([<实参表>])除此之外,在子类中不能再通过其它的方法来访问超类中的被覆盖的方法:((<超类名>)<子类实例引用>).<方法名>([<实参表>])即使在超类类体代码中出现的用简单名字调用的成员方法,运行时也有可能是调用子类中的成员方法---如果子类中定义在覆盖方法,而调用的主体又是子类的实例,那么实际调用的就会是子类中定义的覆盖方法.(举例) 方法覆盖示意图 再论构造方法 构造方法用于初始化正在创建的实例对象,只以创建实例时由系统隐含调用.如果一个类没有定义构造方法,系统会自动提供下个默认的构造方法;如果一个类定义了构造方法,系统就不再提供默认的构造方法.构造方法的第一条语句可以是对所在类的另一个构造方法的显式调用,但不能通过该形式直接或间接的调用自身.格式:this([<实参表>]) 再论构造方法(续…) 构造方法的第一条语句也可以是对直接超类中的一个构造方法的显式调用.格式:super([<实参表>])如果没有显式调用,则隐含的调用是super();隐式调用中如果直接超类中没有不带形参的构造方法,将出现编译错误.除Object以外的一个类的任何一个构造方法都是以对另一个构造方法的调用开始的. 扩展抽象类 一个抽象类的作何一个非抽象子类,必须提供该抽象类中的所有抽象方法的实现.一个类既继承其超类中的已经实现的方法,也继承超类中没有实现的方法.一个类只有覆盖实现其超类中的所有abstract方法才能被定义成非抽象类,否则也只能被定义成抽象类. 扩展抽象类(续…) 抽象类可以被看作是一个存储其所有子类的共同方法代码的仓库,这些共同的方法代码可以被所有子类继承.抽象类也可以被看作是对其所有子类的共同行为的描述. 接口 接口是一种引用类型.接口中只能包含有名常量和没有实现的抽象方法.一个类可以通过提供接口中的抽象方法的实现来实现该接口.接口声明了实现该接口的所有类的对象的共同的行为.与超类不同,接口可以多重继承. 接口定义 [public]interface<接口名>[extends<直接超接口名表]{ <类型><有名常量名>=<初始化表达式>;… <返回类型><方法名>(<形参表>);…} 接口定义 由public修饰的接口能被任何包中接口或类访问;没有public修饰的接口只能在所在包内被访问.接口中不能有初始化块和构造方法.接口中的方法不提供具体的实现.接口中的所有方法具有public,abstract属性(不论写出与否). 接口实现 [<修饰符>]class<类名>[extends<直接超类名>]implements<直接超接口名表>{…} 实现接口的同时扩展类 接口类型名字冲突处理 如果两个直接超接口中包含有同名的有名常量:<接口名>.<常量名>如果两个直接超接口中包含有相同签名但返回类型不同的方法,将引发编译错误.如果两个直接超接口中包含有相同签名且返回类型也相同的方法,则继承保留一个.如果类提供方法的实现,则为两接口的共同实现. 引用类型转换 与父子类转换相似.总体规则是指针赋值后能访问到转换后的类型. 包 包是一种用于组织类、建立类名空间和控制类访问的机制.包是类的集合.包是类的容器;类是数据和代码的容器.import语句使得代码可以用简单类名引用其他包中的类. 类成员的可访问性 包与类示意图 访问代码的情况及失败的原因 Object类Object类是java中类层次树的根,是所有其他类的祖先类. 作业 P142:2,3,4