Java编程思想: 接口

本文深入探讨了Java中抽象类和接口的概念及其应用。详细解释了抽象类如何提供通用接口,接口如何实现多重继承,并介绍了完全解耦的设计策略。此外,还提供了具体的代码示例帮助理解。

抽象类和抽象方法

如果一个类提供一个通用的接口供不同子类继承, 它本身的实例化并没有任何意义, 那么可以使用abstract关键字限制其类为抽象类.

一个类只要出现abstract则必须为抽象类, 而抽象类中的抽象方法在子类中必须实现其定义.

abstract class A {
  public void show() {
    func();
  }
  public abstract void func();

}
public class B extends A{
  public void func() {
    System.out.println("B func");
  }
  public static void main(String[] args) {
    B b = new B();
    b.show();
  }
}

 

接口

抽象类允许在类中定义方法. 但接口比抽象类更加的抽象: 它不提供任何具体实现, 只允许创建者确定方法名,参数列表和返回类型.

所以,interface不仅仅是一个极度抽象的类,因为它允许人们通过创建一个能否被向上转型为多种基类的类型,来实现某种类似多重继承变种的特性.

使用关键字interface定义接口, 使用implements实现此接口

interface A {
  void show();
}
class B implements A{
  public void show() {
    System.out.println("B show()");
  }
}
public class C {
  public static void func(A a) {
    a.show();
  }
  public static void main(String[] args) {
    B b = new B();
    // B show()
    func(b);
  }
}

备注: 接口中所有方法默认为public权限, 而且必须为public.

我们可以通过反射机制来验证接口的类为public abstract:

import java.lang.reflect.*;

interface A {
  void fun1();
  void fun2();
}
class B implements A{
  public void fun1() {
    System.out.println("fun1");
  }
  public void fun2() {
    System.out.println("fun2");
  }
}
public class C {
  public static void main(String[] args) {
    try {
      // output:
      // public abstract void fun2()
      // public abstract void fun1()
      Class c1 = Class.forName("A");
      Method[] methods = c1.getDeclaredMethods();
      for (Method m: methods) {
        Class retType = m.getReturnType();
        String name = m.getName();
        String modifiers = Modifier.toString(m.getModifiers());
        if (modifiers.length() > 0)
          System.out.print(modifiers + " ");
        System.out.print(retType.getName() + " " + name + "(");
        Class[] paramTypes = m.getParameterTypes();
        for (int j = 0; j < paramTypes.length; j++) {
          if (j > 0) System.out.print(",");
          System.out.print(paramTypes[j].getName());
        }
        System.out.println(")");
      }
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
  }
}

 

完全解耦

继承有可能使得类与类之间过于紧密. 我们一般可以使用接口将接口和实现相分离.

一种实现的策略是: 定义1个接口A, 定义一个使用此接口的操作类B, 定义1个实现接口的类C, 在C中使用B, 定义N个操作类继承C, 则在C中由于存在向上转型, 则使用这N个操作类.

这种策略的一种扩展形式在于: 我们可以定义多个接口, 在同一个类中实现多个接口. 由于接口和实现可以完全分离, 这样达到完全的解耦.

interface A {
  String name();
  void show(String s);
}

class B {
  public static void func(A a, String s) {
    System.out.println(a.name());
    a.show(s);
  }
}

public class C implements A {
  public String name() {
    return getClass().getName();
  }
  public void show(String s) {
    System.out.println("C " + s);
  }
  public static void main(String[] args) {
    B.func(new C1(), "hello");
    B.func(new C2(), "world");
  }
}

class C1 extends C {
  public void show(String s) {
    System.out.println("C1 " + s);
  }
}

class C2 extends C {
  public void show(String s) {
    System.out.println("C2 " + s);
  }
}

 

Java中的多重继承

类通过实现多个接口来达到多重继承.

interface A {
  void funA();
}
interface B extends A {
  void funB();
}
interface C extends A {
  void funC();
}
interface E extends B, C {
  void funE();
}
public class D implements E {
  public void funA() {
    System.out.println("funA");
  }
  public void funB() {
    System.out.println("funB");
  }
  public void funC() {
    System.out.println("funC");
  }
  public void funE() {
    System.out.println("funE");
  }
  public static void main(String[] args) {
    D d = new D();
    d.funA();
    d.funB();
    d.funC();
    d.funE();
  }
}

但使用多个接口会存在如下的情况: 方法的返回值不同导致继承的类无法进行分别(对于重载来说, 返回值不同的方法依旧为同一个方法.)

interface A {
  int show();
}

interface B {
  void show();
}
public class C implements A, B {
  public int show() {
    return 1;
  }
  public void show() {

  }
  public static void main(String[] args) {
    // ERROR: int show() 和void show() 产生冲突
    C c = new C();
  }
}

出现这个问题,本身说明接口编写不够完善,需要修改接口.

 

适配接口

我们指定一个接口, 只要遵守此接口就可以调用此接口的其它方法.

例如针对Readable接口, 我们只要实现其read方法, 那么使用Scanner(其接受Readable接口)的其它方法(如hashNext, next)就可以读取其read的数据.

import java.nio.CharBuffer;
import java.util.Scanner;
import java.util.Random;

public class RandomWords implements Readable{
  private static Random rand = new Random(47);
  private static final char[] capitals =
      "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
  private static final char[] lowers =
      "abcdefghijklmnopqrstuvwxyz".toCharArray();
  private static final char[] vowels =
      "aeiou".toCharArray();
  private int count;
  public RandomWords(int count) { this.count = count;}
  public int read(CharBuffer cb) {
    if (count-- == 0)
      return -1;
    cb.append(capitals[rand.nextInt(capitals.length)]);
    for (int i = 0; i < 4; i++) {
      cb.append(vowels[rand.nextInt(vowels.length)]);
      cb.append(lowers[rand.nextInt(lowers.length)]);
    }
    cb.append(" ");
    return 10;
  }
  public static void main(String[] args) {
    Scanner s = new Scanner(new RandomWords(10));
    while (s.hasNext()) {
      System.out.println(s.next());
    }
  }
}

 

转载于:https://my.oschina.net/voler/blog/716388

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值