编程学习笔记之Java相关:接口(interface)的概念与使用

      interface,意为接口,也被称为界面,是用来组织应用中的各个类并调节它们之间相互关系的一种结构,更准确的说,接口是用来类间多重继承功能的一种结构。

1):接口概述

      Java中的接口在语法上和类很像:它定义了若干个抽象方法和常量,形成一个属性集合,该属性集合通常对应了某一组功能,主要功能是用来实现类之间多重继承的功能。所谓多重继承,是指一个子类可以拥有多个直接父类,该子类可以继承所有直接父类的成员,比如c++,就支持多重继承,而Java出于简化程序结构的考虑,不再支持类间的多重继承而只支持单向继承,即一个子类只能有唯一一个直接父类。然而在实际情况中,仅仅依靠单重继承在有些情况下不能讲问题的复杂性表述完整,所以需要其它的机制作为辅助。

      由于Java只支持单重继承,所以Java的类层次结构是树状结构,随着类结构树的生长,越是下层的类,所继承的成员会越来越多越来越膨胀,难以管理和掌握。

      为了使Java的类层次结构更加合理,更符合实际问题的本质,用户可以把用于完成特定功能的若干属性组织成相对独立的属性集合:凡是需要实现这种特定功能的类,都可以继承这个属性集合并在类内使用它们,上面所说的属性集合,就是我们今天要讲的接口。

      需要特别注意的是,Java中的一个类获取某一接口定义的功能,并不是通过直接继承这个接口中的属性和方法来实现的,这是因为接口中的属性都是常量,接口中的方法都是没有定义方法体的抽象方法。也就是说,接口定义的仅仅是某一特定功能的对外接口和规范,至于这些功能所需要的方法的具体实现,要在那些类里面定义,因此在Java中,接口的继承其本质是“实现”。

      总之,接口的应用主要有以下两点:1,规定某些类应该实现的方法的调用接口。2,通过定义一个能实现多个接口的类,来模拟类的多重继承。


2):接口的声明

      Java中声明接口的语法如下:

[public] interface 接口名 [extends 父类接口名列表]
{
  //常量域声明
  [public][static][final] 域类型 域名 = 常量值;

  //抽象方法声明
  [public][abstract][native]返回值 方法名(参数列表) [throw异常列表]
}
从上面的规定看,可以把接口理解成一种特殊的类:一个由常量和抽象方法组成的特殊类。一个类只能有一个直接父类,但一个类可以有N个接口,所以这个角度来说,Java是支持多重继承的。

      就像class是声明类的关键字一样,interface是声明接口的关键字,它引导着所定义的接口的名字,这个名字应该符合Java标识符的规定。与类定义相仿,声明接口时也应该给出访问控制符,不同的是接口的访问控制符只有一个public,用public修饰的接口是公共接口,它可以被所有的类和接口使用,而没有public修饰的接口只能被同一个包中其它类或接口访问。

      同样的,接口也具有继承性,定义一个接口时也可以通过extends关键字继承某个或某些已存在的其它接口,这样新定义的接口将继承父接口的所有属性和方法。但与Java中类的不同是,一个接口可以有N个直接父接口,它们之间用【,】分割,形成父接口列表。

      接口体的声明是定义接口的重要部分。接口体由两部分组成:一部分是对接口中属性的声明,一部分是接口中抽象方法的声明。属性都是用final修饰的常量,而方法都是用abstract修饰的抽象方法,在接口声明中只能给出这些方法的名字、返回值、参数列表,而不能具体定义方法体【要在继承接口的类中定义】,即仅仅规定了一组信息交换、传输和处理的“接口”。其中,接口的属性必须是【public static final】,所以在声明时,我们可以不用加这些修饰符,因为这是Java默认的。同样的,方法体也必须是【public abstract】,无论是否有修饰符显式限定它。

      需要特别注意的是,Java接口中方法的方法体可以由其它语言书写,在这种情况下,接口方法可以由native修饰。

      在Java的系统类库中有不少使用接口的例子,下面就给出一个系统定义的接口DataInput:

public interface java.io.DataInput
{
	public abstract boolean readBoolean();                  //读入布尔型数据
	public abstract byte readByte();                        //读入字节型数据
	public abstract char readChar();                        //读入字符型数据
	public abstract double readDouble();                    //读入双精度数据
	public abstract float readFloat();                      //读入浮点型数据
	public abstract void readFully(byte b[]);               //将读入的全部数据存入字节数组b
	public abstract void readFully(byte b[],int off,int len);//将读入的全部数据存入到指定位置
	public abstract int readInt();                          //读入整型数据
	public abstract String readLine();                      //读入一行
	public abstract long readLong();                        //读入长整型数据
	public abstract short readShort();                      //读入短整型数据
	public abstract int readUnsignedByte();                 //读入无符号的字节数据
	public abstract int readUnsignedShort();                //读入无符号的短整型数据
	public abstract String readUTF();                       //读入UTF数据
	public abstract int skipBytes(int n);                        //将读取位置跳过n个字节
}
      在上面这个接口中定义了大量的读取各种类型数据的方法,Java中最基本的输入输出被定义为流式输入输出,即不用理解数据的真正含义和它们的实际类型,而仅仅把它们看成一道比特流而已,这是一种很低级的输入输出方式,需要应用程序来完成对比特流的理解和转化,为了简化编程,Java中除了定义了上面的DataInput之外,还定义了与之对应的DataOutput接口,并在这两个接口中定义了大量的按照数据类型读取数据的方法,分别代表“按数据类型输入”和“按数据类型输出”的功能,如果使有关输入输出的类来实现这两个接口,那么这些类就具有了较为高级的按数据类型读写的功能。


3):实现接口

      接口的声明仅仅是给出了抽象方法,相当于程序开发早期的一组协议,而要想具体实现接口中所规定的功能,则需要某个类为接口中的抽象方法定义切切实实的方法体。

      一个类在实现接口中,应该注意以下问题:

      1、在类的声明部分,用implements关键字声明该类将要实现哪些接口。

      2、如果实现某接口的类不是abstract抽象类,则在类定义时必须定义实现接口中的所有抽象方法,而且方法头部分要与接口中的声明完全一致!

      3、如果实现某接口的类是abstract抽象类,那么它可以不用定义该接口中的所有抽象方法。但是,继承该抽象类的任何一个非抽象子类,它们父类所实现的接口中的所有的抽象方法都必须要有实在的方法体。这些方法体可以来自抽象的父类,也可以来自子类本身,但决不允许存在没有实现的接口方法!这是因为非抽象类不能存在抽象方法的原因。

      4、一个类在实现某接口中的抽象方法时,方法头要完全一致,如果实现的方法和接口中声明的方法不同命或者有不同的参数列表等,那么这只是重载了一个方法,而非实现方法。

      5、因为接口中的抽象方法都默认为public,所以某个类在实现某个接口时,定义该接口中的抽象方法时,也必须用public修饰!否则会被系统警告为缩小了接口中定义的方法的访问控制范围。



      最后我们来看一个实现ActionListeners接口的实际例子:

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class ImplementActoinListener extends Applet implements ActionListener{
	TextField password = new TextField("w s 密码");
	Button btn = new Button("隐藏");
	public void init()
	{
		add(password);
		add(btn);
		btn.addActionListener(this);
	}
	
	public void actionPerformed(ActionEvent e)
	{
		password.setEchoChar('A');
		password.selectAll();
	}
}

在上面的代码中,程序第5行声明了主类ImplementActionListener将实现ActionListener接口,而第15到第19行重新定义了ActionListener接口中声明的方法actionPerformed,其作用是响应用户单击按钮“隐藏”的动作,把文本框password中的字符用“*”代替并选中其中的文字。

      而ActionListener接口的定义如下:

public abstract interface ActionListener extends EventListener{
  public void actionPerformed( ActionEvent e);
}

这里的EventListener是ActionListener的父接口,里面的actionPerformer方法是默认的abstract方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值