第九章 接口
9.1 抽象类与抽象方法
建立抽象类是希望通过这个接口操作一系列类。
- 包含抽象方法的类叫做抽象类。如果类含有抽象方法,则必须被限定为抽象的。
- 如果继承抽象类,并创建该新类的对象,则必须事先基类中所有的抽象方法提供定义。
- 否则导出类也是抽象类,且会被编译器强制用abstract关键字限制。
9.2 接口
interface允许在类中创建一个或多个没有任何定义的方法。它允许创建具体的方法名,参数列表和返回值类型,但是没有任何的方法体。及入口仅提供了具体的定义,没有实现。
- 接口中可以定义域,但是默认是static的
- 接口中的方法必须是public的(也是默认的情况)。因为不定义为public,方法只能得到包的访问权限,这样在被继承的过程中,访问权限就被降低了。
9.2 完全解耦
在继承(extends)中,多态只能体现在继承类上,如果将其应用于非继承类上,则会产生错误。
9.2.1 策略模式
创建一个能够根据输入参数对象的不同而具有不用行为的方法,本称为“策略”设计模式。策略模式和继承的多态有区别,即通过interface,策略模式可以接收对象的范围突破了继承关系。
若无法修改想使用的类,可以使用适配器模式,适配器代码中将接受类中所有的接口,并且产生所需的接口。
//: interfaces/interfaceprocessor/Processor.java
package interfaces.interfaceprocessor;
public interface Processor {
String name();
Object process(Object input);
} ///:~
public abstract class StringProcessor implements Processor{
public String name() {
return getClass().getSimpleName();
}
public abstract String process(Object input);
public static String s =
"If she weighs the same as a duck, she's made of wood";
public static void main(String[] args) {
Apply.process(new Upcase(), s);
Apply.process(new Downcase(), s);
Apply.process(new Splitter(), s);
}
}
class Upcase extends StringProcessor {
public String process(Object input) { // Covariant return
return ((String)input).toUpperCase();
}
}
class Downcase extends StringProcessor {
public String process(Object input) {
return ((String)input).toLowerCase();
}
}
class Splitter extends StringProcessor {
public String process(Object input) {
return Arrays.toString(((String)input).split(" "));
}
} /* Output:
Using Processor Upcase
IF SHE WEIGHS THE SAME AS A DUCK, SHE'S MADE OF WOOD
Using Processor Downcase
if she weighs the same as a duck, she's made of wood
Using Processor Splitter
[If, she, weighs, the, same, as, a, duck,, she's, made, of, wood]
*///:~
9.4 Java中的多重继承
在Java中可以实现多个接口,以表达:x是一个a和b和c。
9.5 通过继承来拓展接口
一般情况下,只可以将extends用于单一的类,但是可以引用多个基类接口。接口继承接口,类继承接口。
9.5.1 组合接口时的名字冲突
实现多重继承时,可能会出现命名冲突的问题。相同的方法不会出现问题,方法重载也不会出现问题。但是根据返回值无法区分方法时则会出现问题。
//: interfaces/InterfaceCollision.java
interface I1 { void f(); }
interface I2 { int f(int i); }
interface I3 { int f(); }
class C { public int f() { return 1; } }
class C2 implements I1, I2 {
public void f() {}
public int f(int i) { return 1; } // overloaded
}
class C3 extends C implements I2 {
public int f(int i) { return 1; } // overloaded
}
class C4 extends C implements I3 {
// Identical, no problem:
public int f() { return 1; }
}
// Methods differ only by return type:
// 类C和接口I1中有相同的f()方法,返回值不同,
// 但是此类情况无法区分方法
//! class C5 extends C implements I1 {}
// 原因同上。
//! interface I4 extends I1, I3 {} ///:~
9.6 适配接口
接口:你可以用任何你想要的对象来调用我,只要你的对象遵循了我的接口。
接口一种常见的用法为策略模式,若无法在原类上修改,可以使用代理模式。
9.7 接口中的域
放入接口中的任何域都自动是static和final的。这些域应当在定义时被初始化。但是这些域并不是接口的一部分,它们的值被存储在该接口的静态存储区内。
9.8 接口嵌套
没有看懂。
9.9 接口与工厂
实现代码与接口的分离。在具体的实现类里面实现接口,在工厂类方法中调用具体的实现类的创建方法。
9.10 总结
虽然接口带来了方便,但还是应该在使用时多加思考。