Java编程之面向接口
本篇内容:
1.接口的引入
2.接口的实现
3.抽象类与接口的区别
4.小结
1.接口的引入
?????????接口,类似于实际生活中的插座接口,只要你的插头符合接口的规范,比如大小、形状等,那么你的插头就能使用这个插座接口。 ?????????**接口不是类,但类似于类。此话怎讲?我们先瞧瞧接口到底是如何在Java中实现的,为啥要使用接口呢?**请先看一个例子:假设需要实现一个 U 盘和一个硬盘类,都有传送数据的方法,初步实现如下:
public class U盘 {
public void service() {
System.out.println("U盘开始传送数据");
}
}
public class 硬盘 {
public void service() {
System.out.println("硬盘在传送数据");
}
}
?
public class 电脑 {
public void 传送数据(硬盘 usb) {
usb.service();
}
public void 传送数据(U盘 usb) {
usb.service();
}
}
?????? 上述编码方式是伪代码,但是不难看出代码的设计显然不合理,再加一个同样可以用来传输数据的手机或者相机类,那么电脑上又要添加更多方法了,如何更改并优化这种设计方式呢? ?????? 如果使用继承,然后使用方法重写,利用参数类型实现多态来优化这段代码,那么必须提供一个父类,很显然这几个类没有特别明显的继承、包含之类的关系,也就是说父类很难找到,没有通用性。那么是否可以把这个传送数据的方法作为一个单独的、统一的、独立的功能作为某种规范定义出来呢?答案是可以的,这个统一功能的定义即所谓的接口,可以用来代替以上实现传输数据的统一标准手段:
public interface USB {
public void service();
}
- 由此可以知道接口实际上就是一种规范,接口没有任何具体实现,只是记录了一些规定,而任何符合了这些规定或者说实现了这些规定的对象都可以看做这种接口的实现,可以用来做某类事情。
2.接口的实现
?????? 在 Java 中接口定义使用 interface 关键字,创建方式和类文件完全一样:
public interface MyInterface{
void method1();
public int method2(String arg);
}
public interface IEmpty{
}
- 实现接口的类使用 implements 关键字,并且必须实现接口中定义的方法:
public class A implements MyInterface{
public void method1(){
}
public int method2(String arg){
}
}
- 类最多只能继承于一个父类,但是可以实现多个接口,接口之间用 , 逗号隔开:
public class B extends A implements MyInterface, IEmpty{
}
- 接口与接口之间也具备扩展的概念,同样使用 extends 关键字:
public interface MyInterface extends Iterable, Comparable, Cloneable{
void extend();
}
- 注意,接口可以多继承,接口也只能继承接口而不是类。实际上,接口的继承类似于整合的概念,同时也具备了多态中的继承关系:
public interface A{}
public interface B{}
public interface C extends A, B{}
public interface D{}
public class X implements C, D{}
public static void main(String[] args) {
X obj = new X();
System.out.println(obj instanceof A);
System.out.println(obj instanceof B);
System.out.println(obj instanceof C);
System.out.println(obj instanceof D);
System.out.println(obj instanceof X);
}
- 正因为接口, Java 编程灵活性也大大增强,面向接口编程也能够让代码更具有灵活性、扩展性,伪代码示例:
public interface 编程 {
public void 编写程序();
}
public interface 业务 {
public void 分析业务();
}
?
public class Java程序员 implements 编程, 业务 {
public void 编写程序() {
System.out.println("使用Java编程");
}
public void 分析业务() {
System.out.println("仔细分析业务");
}
}
内部接口
有些类可能依赖一个简单的接口,而这个接口在外部定义意义不大,那么可以把接口直接定义在类中,通过类名.接口名使用该接口,这样的接口叫内部接口:
public class A{
interface B{
void f();
}
public void doSomething(B obj){
obj.f();
}
}
public static void main(String[] args) {
new A().doSomething(new A.B(){
@Override public void f(){ }
});
}
public interface I1{
void f1();
interface I2{
void f2();
}
}
?
class MyClass implements I1.I2{
@Override public void f2() {}
}
接口属性
接口定义了一串由具体类实现的抽象方法,那么接口是否可以定义属性呢?答案是肯定的,和类中属性的定义类似:
interface MyInterface{
int CONSTANT_A = 100;
double CONSTANT_B = Math.random();
public static final String CONSTANT_C = "hello";
}
?
public class MyClass implements MyInterface{}
?
public static void main(String[] args) {
System.out.println(MyInterface.CONSTANT_A);
System.out.println(MyClass.CONSTANT_C);
}
- 可以看到,也可以通过实现了接口的类来直接引用接口中定义的变量,注意:接口中的属性默认为 public,static,final 即使省略也无法修改,也就是静态常量,所以一般都是使用大写加下划线的方式命名。
接口默认值
接口允许使用默认实现,通过 default 关键字实现:
interface MyInterface{
int count();
default void result() {
System.out.println("默认计数器:" + count());
}
}
class A implements MyInterface{
@Override public int count(){
return 100;
}
}
class B implements MyInterface{
@Override public int count(){
return 50;
}
@Override public void result() {
System.out.println("自定义计数器:" + (count() + 200));
}
}
public static void main(String[] args) {
new A().result();
new B().result();
}
???????可以看到,默认方法可以在接口中写方法体,而实现类可以不必重写 default 修饰的默认方法。这样做的好处是:当我们需要给接口新增一个方法时,会涉及到所有实现该接口的类,如果新增的是 default 默认方法,那么实现类就不需要全部修改也可以编译成功,而需要具体实现的仍然可以按需重写新增方法即可。
???????抽象类中的普通方法也是可以正常实现,不过不同的是,抽象类中方法可以访问类中字段,而接口中默认方法无法访问实现类的字段。
3.抽象类与接口的区别
相同点: (1)都不能被实例化 (2)接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能实例化。
不同点: (1)接口只有定义,不能有方法的实现,java 1.8中可以定义default方法体,而抽象类可以有定义与实现,方法可在抽象类中实现。 (2)实现接口的关键字为implements,继承抽象类的关键字为extends。一个类可以实现多个接口,但一个类只能继承一个抽象类。所以,使用接口可以间接地实现多重继承。 (3)接口强调特定功能的实现,而抽象类强调所属关系。 (4)接口成员变量默认为public static final,必须赋初值,不能被修改;其所有的成员方法都是public、abstract的。抽象类中成员变量默认default,可在子类中被重新定义,也可被重新赋值;抽象方法被abstract修饰,不能被private、static、synchronized和native等修饰,必须以分号结尾,不带花括号。 (5)接口被用于常用的功能,便于日后维护和添加删除,而抽象类更倾向于充当公共类的角色,不适用于日后重新对立面的代码修改。功能需要累积时用抽象类,不需要累积时用接口。
4.小结
- 以上就是接口的基本内容,总的来说接口的特点有以下几点:
(1)接口定义的方法不能有具体实现(可以使用 default 默认实现),仅仅作为规范和标准 (2)接口类似抽象类不能实例化,但是可以作为引用类型,实现多态 (3)接口中的方法默认为 public abstract ,任何实现了接口的类必须重写接口的所有方法 (4)如果类实现了接口,但是依然没有把所有方法具体实现,那么类必须修饰为抽象类 (5)一个类可以实现多个接口,这与单继承不一样,同时可以通过接口类型实现多态 (6)接口之间可以继承,而且可以是多继承,与类的单继承不一样
|