版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、JAVA类和对象高级特征,接口 内部类 JAVA中的文档注释,4.1、接口,1、接口的概念 在Java中,出于简化程序结构的考虑,不再支持类间的多重继承而只支持单重继承,即一个类至多只能有一个直接父类。然而在解决实际问题的过程中,仅仅依靠单重继承在很多情况下都不能将问题的复杂性表述完整,需要其他的机制接口作为辅助。 接口主要作用是可以帮助实现类似于类的多重继承的功能。,C+的多继承中的问题:二义性 (1)两个基类具有同名的成员。如: class Base1 public: void fun() ; class Base2 public: void fun() ; class Derived:
2、public Base1,public Base2 ; int main() Derived obj; obj.fun(); /将产生二义性 ,(2)派生类继承的多个基类拥有同一个基类(祖先类),则对其共同的基类(祖先类)成员访问时会有二义性。 class Basepublic: int data; class Derived11:public Base ; class Derived12:public Base ; class Derived2:public Derived11, public Derived12 ; int main() Derived2 obj; obj.data=1;
3、/产生二义性 ,JAVA单继承的问题 (1) JAVA的单继承,它的类层次结构是树状结构。有时对处理复杂问题会力不从心; (2) 随着类结构树的增长,越是处在下层的子类,它的间接父类(祖先类)越多,所继承的方法也会越来越多,造成子类成员的膨胀、庞杂,难以管理和掌握。,解决问题的思路: 采用多继承方案,但同时又没有C+多继承的二义性问题。 (1) 把用于完成特点功能的若干属性组织成相对独立的属性集合;凡是需要实现这种特点功能的类,都可以继承这个属性集合,并在类内使用它,这种属性集合就是接口。 (2)接口定义的仅仅是实现某一特定功能的一组功能的对外接口和规范,而并没有真正实现这一功能。(抽象方法)
4、 (3) JAVA中的一个类获取某一接口定义的功能,并不是通过直接继承这个接口中的属性和方法来实现。因为接口中并没有真正的实现,因此需要在JAVA类中具体定义各抽象方法的方法体。JAVA中把对接口功能的“继承”称为“实现”。,某游戏类继承关系局部,代码:sourceex4sourcesotherWeaponConsole.java,2、定义接口 Java中声明接口的语法如下: public interface 接口名 extends 父接口名列表 /接口体; /常量域声明 public static final 域类型 域名=常量值; /抽象方法声明 public abstract nativ
5、e 返回值 方法名(参数列表) throw异常列表; 从上面的语法规定可以看出,定义接口与定义类非常相似,实际上完全可以把接口理解成为一种特殊的类,接口是由常量和抽象方法组成的特殊类。 接口也可以有自己的父类,这时要用到extends关键字。,接口与类的区别 (1)接口中不能定义成员变量,只能定义成员常量。 (2) 接口中的成员方法或称成员函数只能有声明,既只能定义方法名、返回类型、参数以及访问控制修饰(Public或Private或Protected),不能有大括号以及其中的内容,也就是说不能有实现方法的任何代码。 (3)接口可以继承多个接口类,也就是说一个接口类可以有多个类型为接口的父类。
6、 (4)接口与前面所讲的final类恰恰相反,接口类必须被继承并实现,如果其子类没有完全实现该接口所定义的方法,那么该子类必须定义为抽象类。 (5)接口类的子类除实现该接口类之外,还可以实现其它的接口类。,3、实现接口 (1)在类的声明部分,用implements关键字声明该类将要实现哪些接口; (2)如果实现某接口的类不是abstract的抽象类,则在类的定义部分必须实现指定接口的所有抽象方法,即为所有抽象方法定义方法体,而且方法头部分应该与接口中的定义完全一致,即有完全相同的返回值和参数列表; (3)如果实现某接口的类是abstract的抽象类,则它可以不实现该接口所有的方法。 (4)一个
7、类在实现某接口的抽象方法时,必须使用完全相同的方法头。 (5)接口的抽象方法,其访问限制符都已指定是public,所以类在实现方法时,必须显式地使用public修饰符。,例子4.1 接口的实现 P89 sourceex4sources1 Work.java Manage.java Sale.java,4、接口回调 接口回调是指可以把实现某一接口的类创建的对象的引用赋给该接口声明的接口变量中,那么该接口变量就可以调用被类实现的接口中的方法。实际上,当接口变量调用被类实现的接口中的方法时,就是通知相应的对象调用接口的方法。 类比:如果父类对象与引用指向的实际是一个子类对 象,那么这个父类对象的引用
8、可以用强制类型转换转化成子类对象的引用。,sourceex3sourcesotherClassEx.java,sourceex4sourcesother Example4_1.java,5、接口的多态 (举例) (参见接口回调的例子) interface Access /存取数据接口 void put(char c); char get( ); ,class Stack implements Access private char array =new char80; private int top=0; public void put(char c) arraytop+=c; public
9、char get() return array-top; ,class Queue implements Access private char array=new char80; private int front=0,rear=0; public void put(char c) arrayrear+=c; public char get( ) return arrayfront-; ,class StackQueue public static void main(String args ) Stack s=new STack( ); s.put(a); s.put(b); s.put(
10、c); Queue q=new Queue( ); q.put(a); q.put(b); q.put(c); System.out.println(“nStack:”); System.out.println(s.get( ); System.out.println(s.get( ); System.out.println(s.get( ); System.out.println(“nQueue:”); System.out.println(q.get( ); System.out.println(q.get( ); System.out.println(q.get( ); ,6、接口与抽象
11、类(interface / abstrac class) 相同: abstractclass和interface在Java语言中都是用来进行抽象类。 并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。 抽象类主要用来进行类型隐藏。我们可以构造出一个固定的一组行为的抽象描述,但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类,而这一组任意个可能的具体实现则表现为所有可能的派生类。,不同: (1)在abstract class方式中,类可以有自己的数据成员,也可以有非abstarct的成员方法; 而在interface方式的
12、实现中,接口中只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在interface中一般不定义数据成员),所有的成员方法都是abstract的。从某种意义上说,interface是一种特殊形式的abstract class。,(2) abstract class在Java语言中表示的是一种继承关系,一个类只能使用一次继承关系。 但是,一个类却可以实现多个interface。 abstractclass表示的是“isa”关系,用于单继承关系; interface表示的是“likea”关系,用于多继承。 当父类中可以不带任何方法和变量定义时,应该选用接口而不是抽象类
13、。 也许,这是Java语言的设计者在考虑Java对于多重继承的支持方面的一种折中考虑吧。,(3)在abstractclass的定义中,我们可以赋予方法的默认行为。(抽象类中已经实现的方法) 但是在interface的定义中,方法却不能拥有默认行为。 使用接口,在抽象类中不能定义默认行为,存在另一个比较严重的问题就是维护上的麻烦。例如:如果后来想修改类的界面以适应新的情况(比如给已用的方法中添加新的参数)时,对于派生类很多的情况,需要对派生类中各实现接口的方法进行修改,非常麻烦。但是如果界面是通过abstract class来实现的,那么可能就只需要修改定义在abstract class中的默认
14、行为就可以了。 同样,如果不能在抽象类中定义默认行为,就会导致同样的方法实现出现在该抽象类的每一个派生类中,违反了one rule,one place原则,造成代码重复,同样不利于以后的维护。,例子:假设在我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型。 使用abstractclass方式定义Door:abstractclassDoor abstractvoidopen(); abstractvoidclose(); 使用interface方式定义Do
15、or: interface Door void open(); void close(); ,该例子中,其他具体的Door类型可以extends使用abstractclass方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstractclass和interface没有大的区别。 如果现在要求Door还要具有报警的功能。我们该如何设计针对该例子的类结构呢,方案一: 抽象类 abstract class Door abstract void open(); abstract void close(); abstract void alarm()
16、; class AlarmDoor extends Door void open() void close() void alarm() ,接口: interface Door void open(); void close(); void alarm(); class AlarmDoor implements Door void open() void close() void alarm() ,这种设计方法的问题:违反了面向对象设计中的一个核心原则 ISP( InterfaceSegregationPriciple ),在Door的定义中把Door概念本身固有的行为方法和另外一个概念“报警
17、器”的行为方法混在了一起。这样引起的一个问题是:那些仅仅依赖于Door这个概念的模块会因为“报警器”这个概念的改变(比如:修改alarm方法的参数)而改变,反之依然。 到底是门还是报警器?,其它方案: 既然open、close和alarm属于两个不同的概念(一个是门,一个是报警器),根据ISP原则应该把它们分别定义在代表这两个概念的抽象类中。定义方式有: (1)这两个概念都使用abstractclass方式定义; (2)两个概念都使用interface方式定义; (3)一个概念使用abstractclass方式定义,另一个概念使用interface方式定义。,分析: (1)由于Java语言不支
18、持多重继承,所以两个概念都使用abstractclass方式定义是不可行的。 (2)如果两个概念都使用interface方式来定义,那么就反映我们可能没有理解清楚问题领域:AlarmDoor在概念本质上到底是Door还是报警器? (3)我们对于问题领域的正确的理解是:AlarmDoor在概念本质上是Door,同时它有具有报警的功能。abstractclass在Java语言中表示一种继承关系,而继承关系在本质上是isa关系。所以对于Door这个概念,我们应该使用abstarctclass方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行为,所以报警概念可以通过
19、interface方式定义。,实现方法: abstractclassDoor abstractvoidopen(); abstractvoidclose();interfaceAlarm voidalarm();classAlarmDoorextendsDoorimplementsAlarm voidopen() voidclose()voidalarm(),2、内部类,一个类中除了定义该类的成员变量和方法之外,还可以定义一个类,这种在一个类中定义的类称为内部类。 因此包含内部类的类称为外部类。 示例如下:,class Outer int Outer_i = 100; void test()
20、Inner inner = new Inner(); inner.display(); class Inner /定义内部类 void display() System.out.println(“Outer_i = “ + Outer_i); public static void main(String args) Outer outer = new Outer(); outer.test(); ,1、内部类特性 (1)内部类可以直接访问外部类的成员变量和方法。 而外部类就不可以直接访问内部类的成员变量和方法。,class Outer int Outer_i = 100; void test(
21、) Inner inner = new Inner(); inner.display(); System.out.println(“Inner_i = ” + Inner_i); class Inner int Inner_i = 200; void display() System.out.println(“Outer_i = “ + Outer_i); public static void main(String args) Outer outer = new Outer(); outer.test(); /代码sourceex4sourcesotherOuter.java,错误:不能访问
22、内部类的成员变量,正确:能访问外部类的成员变量,(2)当函数的局部变量(函数的参数即形参也是局部变量)、内部类的成员变量以及外部类的成员变量名称相同时,应该采用以下的程序代码所使用的方式来明确指定我们真正要访问的变量。 示例如下:,public class Outer private int Size; public class Inner private int Size; public void doStuff(int Size) Size+; / 引用的是doStuff()函数的形参 this.Size+;/ 引用的是Inner内部类的成员变量 / 下面引用的是Outer外部类的成员变量
23、 Outer.this.Size+; ,2、静态内部类 (1)内部类中不能定义static静态成员,除非该内部类也声明为static静态。 (2)一旦一个内部类被声明为static静态的,那该内部类就和外部类一样。并且可以不用初始化外部类而直接使用内部类。 (3)静态内部类相当与一个外部类,因此不能在静态内部类中直接访问外部类的成员。 代码:sourceex4sourcesotherOuter2.java,3、内部类的引用 (1)定义的内部类是public的,这样定义的内部类可以被其它类使用,而不仅仅是在定义该内部类的外部类中被使用。 (2)在调用到访问外部类成员变量的内部类方法时,一定要确保该外部类对象的存在。 (3)首先要创建外部类的一个实例对象;再通过指定外部类的实例对象,并通过”.”操作符和new来创建内部类的实例对象inner;参见例子程序。 代码:sourceex4sources7TestInner.java,4、方法中内部类的使用 (1)除了在类中定义内部类之外,还可以在方
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 译林版(三起)五年级上册 Grammar Time 语法课时精练(全册8单元)
- 换季健康防护指南
- 职业培训发展规划范本
- 人工智能激光雷达技术详解
- 昆山安全经验分享讲解
- 2026年餐饮加盟合作经营合同三篇
- 2026城市聚落面试题及答案
- 2026道路执法面试题库及答案
- 2026东盟财经面试题及答案
- 2026年赣州高考化学全程复习规划与备考指南
- (正式版)JTT 1497-2024 公路桥梁塔柱施工平台及通道安全技术要求
- (高清版)DZT 0293-2016 井中磁测技术规程
- 《老年人多重用药安全管理专家共识》解读课件
- 义务教育科学课程标准(2022年版)
- 深圳市工务署品牌库
- 构件式玻璃幕墙施工方案
- GB/T 10051.3-2010起重吊钩第3部分:锻造吊钩使用检查
- GA/T 1567-2019城市道路交通隔离栏设置指南
- 应急联锁设备设施专项检查表
- DB11T 2000-2022建筑工程消防施工质量验收规范
- 工勤技能考试职业道德试题册及答案
评论
0/150
提交评论