- 抽象类
abstract void f();
包含抽象方法的的类叫做抽象类。如果一个类包含一个或者多个抽象方法,该类必须限定为抽象的。
创建抽象类和抽象方法非常有用,因为它们可以使类的抽象性明确起来,并告诉用户和编译器打算怎样来使用它们。
抽象类还是很有用的重构工具,因为它们使我们可以很容易地将公共方法沿着继承层次向上移动。
- 接口
接口中,方法不添加关键字的话,则默认为public。
【代码:Music5.java】
package source.gohome01;
import source.saterday.Note;
interface Instrument {
int VALUE = 5; //static && final
void play(Note n); //Automatically public
void adjust();
}
class Wind implements Instrument {
public void adjust() { System.out.println(this + ".adjust()"); }
public void play(Note n) { System.out.println(this + ".play()" + n); }
public String toString() { return "Wind"; }
}
class Percussion implements Instrument {
public void adjust() { System.out.println(this + ".adjust()"); }
public void play(Note n) { System.out.println(this + ".play()" + n); }
public String toString() { return "Percussion"; }
}
class Stringed implements Instrument {
public void adjust() { System.out.println(this + ".adjust()"); }
public void play(Note n) { System.out.println(this + ".play()" + n); }
public String toString() { return "Stringed"; }
}
class Brass extends Wind {
public String toString() { return "Brass"; }
}
class WoodWind extends Wind {
public String toString() { return "WoodWind"; }
}
public class Music5 {
static void tune(Instrument i) {
i.play(Note.MIDDLE_C);
}
static void tuneAll(Instrument[] e) {
for(Instrument i: e)
tune(i);
}
public static void main(String[] args) {
Instrument[] orchestra = {
new Wind(),
new Percussion(),
new Stringed(),
new Brass(),
new WoodWind()
};
tuneAll(orchestra);
}
}
output:
- 利用接口实现完全解耦
package source.gohome01;
import java.util.Arrays;
class Processor {
public String name() {
return getClass().getSimpleName();
}
Object process(Object input){
return input; //Object是所有类的基类,此方法可以在导出类中将返回值和形参改为具体类型
}
}
class Upcase extends Processor {
String process(Object input) {
return ((String)input).toUpperCase();
}
}
class Downcase extends Processor {
String process(Object input) {
return ((String)input).toLowerCase();
}
}
class Splitter extends Processor {
//the split() argument divides a String into pieces.
String process(Object input) {
return Arrays.toString(((String)input).split(" "));
}
}
public class Apply {
public static void process(Processor p, String s) {
System.out.println("Using Processor: " + p.name());
System.out.println(p.process(s));
}
public static String s =
"Disagreement with beliefs is by definition incorrect";
public static void main(String[] args ) {
process(new Upcase(), s);
process(new Downcase(), s);
process(new Splitter(), s);
}
} // 此为策略模式:创建一个能够根据所传递的参数对象的不同而具有不同行为的方法。
//new Upcase(),new Downcase(),new Splitter()均导出自Processor(),从而实现多态。
加入想复用Apply.process() 的代码,但是由于该函数原型为:
public
static
void
process(Processor p, String s)
第一个参数必须导出自Processor才可以,所以此时如果将Processor改为接口则使用起来更为方便。
【代码StringProcessor.java】
package source.gohome01;
import java.util.Arrays;
class Apply01 {
public static void process(Processor01 p, Object s) {
System.out.println("Using Processor: " + p.name());
System.out.println(p.process(s));
}
}
interface Processor01 {
String name();
Object process(Object input);
}
class Upcase01 extends StringProcessor {
public String process(Object input) {
return ((String)input).toUpperCase();
}
}
class Downcase01 extends StringProcessor {
public String process(Object input) {
return ((String)input).toLowerCase();
}
}
class Splitter01 extends StringProcessor {
//the split() argument divides a String into pieces.
public String process(Object input) {
return Arrays.toString(((String)input).split(" "));
}
}
public abstract class StringProcessor implements Processor01{
public String name() {
return getClass().getSimpleName();
}
public abstract Object process(Object input) ;
public static String s =
"If she weighs the smae as a duck,she's made of wood.";
public static void main(String[] args ) {
Apply01.process(new Upcase01(), s);
Apply01.process(new Downcase01(), s);
Apply01.process(new Splitter01(), s);
}
}
//Apply.process 的第一个参数改为接口类型
//客户端遵循接口来编写自己的类 StringProcessor,其他类继承之
output:
为了解决耦合问题,也可以使用适配器模型,详见《Thinking in Java》P177
- 接口中的域