⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 java04_11.htm

📁 JAVA的课件
💻 HTM
字号:
<html>

<head>
<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Java程序设计</title>
</head>

<body background="Bg.gif">

<p align="center"><font size="5"><b>§4.11 接口</b></font></p>  
  
<p align="left"> &nbsp; 接口是Java中用来实现多重继承的一种结构。它无论是从组织形式还是使用角度来看,都可以看成是一中特殊的抽象类。</p>  
  
<p align="left">&nbsp;&nbsp;&nbsp; 接口使用interface定义,也由成员变量和成员方法两部分构成,可以继承其它接口,也可以被其它接口和类继承——当类继承接口时一般称为“实现”</p>  
  
<p align="left">一、定义接口</p>  
  
<p align="left">&nbsp;&nbsp;&nbsp;   
用户可以自行定义接口,一旦接口被定义,任何类都可以实现它,并且,一个类可以实现多个接口。接口的定义如下:</p>  
  
<p align="left">[修饰符] interface 接口名 [extends 父接口1,父接口2,...]{<br>  
&nbsp;//定义成员变量&nbsp;<br>  
&nbsp; [public][static][final] 数据类型&nbsp; 变量名=初始值;<br>  
&nbsp;&nbsp; .........<br>  
&nbsp;//定义成员方法<br>  
&nbsp; [public][abstract]返回类型&nbsp; 方法名([参数列表]);<br>  
}</p>  
<p align="left">&nbsp;&nbsp;&nbsp; 上面的说明中,interface表明这是一个接口,[修饰符]是访问权修饰符,和类一样,默认访问权是包访问权,我们一般用public来修饰它。和类有区别的是,接口都是abstract的。</p>  
<p align="left">&nbsp;&nbsp;&nbsp; extends和类中的一样,表明后面是接口的父接口。注意,这里的父接口可以有若干多个。接口的继承和类的继承基本原则是一样的,但是更简单(原因稍候就会看到)。</p>  
<p align="left">&nbsp;&nbsp;&nbsp; 接口中的成员变量都是<b>常量</b>。在缺省情况下,接口中的成员变量具有:<br>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static   
final<br>  
所联合规定的属性,这三个修饰符中,static和final没有替代的关键字,这意味所有的成员变量都是静态的、最终的,所以也就是常量。唯一可能改变的是访问权限修饰符public,但在接口中,不允许使用protected和private关键字,这意味着所有的变量都是public类型的。</p>  
<p align="left">&nbsp;&nbsp;&nbsp;   
接口中的成员方法都是抽象方法。在缺省情况下,接口中的成员方法具有:<br>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public   
abstract<br>  
所联合规定的属性。同样public在这里不可改变,abstract没有可以替代的关键字,又由于abstract和static不可联合使用,所以不可能是静态方法,故所有的方法都是具有public访问权限的抽象实例方法。</p>  
<p align="left">&nbsp;&nbsp;&nbsp;  
接口的方法都是抽象的,而构造方法不可能为抽象方法,自然也就没有抽象的构造方法。</p> 
<p align="left">二、接口的继承&nbsp;</p> 
<p align="left">&nbsp;&nbsp;   
由于接口中的成员修饰符比类中的要简单得多,所以继承时的情况也简单得多。下面我们来看一个简单的例子。</p>  
<p align="left">interface BaseColors {<br>   
&nbsp; int RED = 1, GREEN = 2, BLUE = 4; //这里都是静态公共常量<br>  
&nbsp; int getColorValue(int color);&nbsp;&nbsp;&nbsp;&nbsp; //这是一个抽象的公共方法<br>  
}<br>  
<br>  
interface RainbowColors extends BaseColors { //以BaseColors为父接口<br>  
&nbsp; int YELLOW = 3, ORANGE = 5, INDIGO = 6, VIOLET = 7;&nbsp; //新增加了4个成员常量<br>  
&nbsp; //这个接口自动继承了父接口的3个成员常量和1个方法<br>  
}<br>  
<br>  
interface PrintColors extends BaseColors {<br>   
&nbsp; int YELLOW = 8, CYAN = 16, MAGENTA = 32;<br>   
&nbsp; int getColorValue(int color);&nbsp; //这里覆盖了父接口的成员方法,但它仍然是抽象的<br>  
&nbsp; int   
getColorValue();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //还可以重载<br>  
}</p>  
<p align="left">&nbsp;&nbsp;&nbsp;   
在上面的例子中,最后一个接口覆盖了父接口中的方法,这虽然没有语法错误,但实际上是多此一举。</p>  
<p align="left">&nbsp;&nbsp;&nbsp;   
这里例子都是单继承,所以很简单。但接口最重要的作用是实现多重继承,这就可能会出现歧义,我们看下面这个例子:</p>  
<p align="left">interface LotsOfColors extends RainbowColors, PrintColors {//这是多重继承<br>  
&nbsp;&nbsp; int FUCHSIA = 17, VERMILION = 43, CHARTREUSE = RED+90;<br>   
}<br>   
&nbsp;&nbsp;&nbsp; 这里的LotsOfColors同时以RainbowColors和PrintColors为父接口,这样它就同时拥有父接口所有成员方法(2个)和成员常量(14个)。我们注意到,RainbowColors和 PrintColors中有一个同名的常量:YELLOW,只是值不同,这就会出现歧义。</p>  
<p align="left">&nbsp;&nbsp;&nbsp;   
虽然在编译这些接口时并不会报错,但一旦有某个类实现LotsOfColors方法,并引用YELLOW这个量时,就会出现编译错误。</p>  
<p align="left">&nbsp;&nbsp;&nbsp;   
还有一种常见的歧义是关于成员方法的,把前面的例子改一下:</p>  
<p align="left">interface BaseColors {<br>   
&nbsp; int getColorValue(int color);&nbsp;&nbsp;&nbsp;&nbsp; //这是一个抽象的公共方法<br>  
}<br>  
<br>  
interface RainbowColors extends BaseColors{&nbsp;<br>  
&nbsp; void getColorValue();<br>  
&nbsp; //它还自动继承了int getColorValue(int color)<br>  
}<br>  
<br>  
interface PrintColors extends BaseColors {<br>   
&nbsp;&nbsp; int getColorValue();<br>  
&nbsp; //它也自动继承了int getColorValue(int color)<br>  
}</p>  
<p align="left">interface LotsOfColors extends RainbowColors, PrintColors {//这是多重继承<br>  
}<br>  
&nbsp;&nbsp;&nbsp; 我们注意到LotsOfColors分别从RainbowColors和PrintColors中继承了一个int   
getColorValue(int color)方法,这两个方法完全一样。由于它们都是抽象方法,所以在LotsOfColors中只会保留一份,这样在类实现接口的时候也只要实现一个就可以了。在大多数情况下,程序员根本不必考虑这些细节问题,这也是用接口来实现多重继承最大的优势。</p>  
<p align="left">&nbsp;&nbsp;&nbsp; 真正会产生歧义的是void   
getColorValue()和int getColorValue()方法,由于它们的名称相同,参数相同,只有返回值不同,所以它们既不是重载又不是覆盖,编译器将不知道让LotsOfColors继承哪一个。幸运的是这种错误将会由编译器在编译时指出,无需程序员操心。所以程序员只要注意别让成员常量产生歧义就可以了。</p>  
<p align="left">三、接口的实现</p> 
<p align="left">&nbsp;&nbsp;&nbsp;  
接口最终是要给类来实现的。若干没有继承关系的类可以实现同一个接口,一个类也可以实现多个接口,这些接口都称为该类的父接口或超接口。由于接口中只有抽象方法,所以一个非抽象的类必须实现父接口中<b>所有</b>的抽象方法。若父接口继承了其它的接口,则这些接口的抽象方法也要由该类来完成。若是该类同时是某些类的子类,而其父类实现了这些接口中的一部分方法,则该类只要能继承这些方法,也就视为对这些抽象方法的实现。</p> 
<p align="left">&nbsp;&nbsp;&nbsp;  
抽象类不受此限制,因为它可以将实现抽象方法的任务交由它的子类来完成。</p> 
<p align="left">&nbsp;&nbsp;&nbsp;  
我们先来看看类实现接口的一般形式:</p> 
<p align="left">[类修饰符] class 类名 [extends 父类名] [implements  
接口名1[,接口名2,...]]<br> 
{ //类体<br> 
&nbsp; //实现接口中的抽象方法<br> 
&nbsp;&nbsp;&nbsp; <b>public</b> [返回值类型] 方法名([参数表]){&nbsp;<br> 
&nbsp;&nbsp;&nbsp; ......}<br> 
}</p> 
<p align="left">&nbsp;&nbsp;&nbsp; 
注意类在实现接口中的方法时,方法的访问权必须声明成public型(why?),它的参数、返回值也要和接口中的形式完全一致。下面我们来看一个完整的例子:</p>
<p align="left">public interface Colorable {<br> 
&nbsp;&nbsp; void setColor(int color);<br> 
&nbsp;&nbsp; int getColor();<br> 
}<br> 
<br> 
public interface Paintable extends Colorable {<br> 
&nbsp;&nbsp; int MATTE = 0, GLOSSY = 1;<br> 
&nbsp;&nbsp; void setFinish(int finish);<br> 
&nbsp;&nbsp; int getFinish();<br> 
&nbsp;}</p>
<p align="left">class Point { int x, y; }<br> 
<br> 
class ColoredPoint extends Point implements Colorable {<br> 
/* 本类必须实现接口Colorable中所有的抽象方法 */<br>
&nbsp; int color;<br> 
&nbsp; public void setColor(int color) { this.color = color; }<br> 
&nbsp; public int getColor() { return color; }<br> 
&nbsp;}<br>
<br>
class PaintedPoint extends ColoredPoint implements Paintable{<br> 
/* 接口Paintable中有4个抽象方法,但PaintedPoint只要实现其中的两个,另两个已经由ColoredPoint实现 
*/<br>
&nbsp; int finish;<br> 
&nbsp; public void setFinish(int finish) {<br> 
&nbsp; this.finish = finish;<br> 
&nbsp;}<br>
&nbsp; public int getFinish() {&nbsp;<br>
&nbsp;&nbsp; return finish;<br> 
&nbsp;}<br>
}<br>
</p>
<p align="left"><a href="index.htm">回目录</a>   <a href="java04_10.htm">上一课</a> 
<a href="java04_12.htm">下一课</a></p>

</body>

</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -