抽象方法:这种方法只有声明而没有方法体,下面是抽象方法生命所采用的语法java
abstract void f();
包含抽象方法的类叫作抽象类,若是一个类包含一个或多个抽象方法,该类必须被限定为抽象的,而且编译器不会容许直接建立一个抽象类对象,正确的作法是从这个抽象类继承并为抽象方法完成定义,这样就能够建立这个类的对象。但若是导出类还有抽象方法,那这个类还应该加上abstract声明为抽象类。简单的使用以下设计模式
package tij.interfacedemo; public class Test { public static void main(String[] args) { new Wind().play(Note.MIDDLE_A); } } enum Note{ MIDDLE_A,MIDDLE_B,MIDDLE_C; } abstract class Instrument{//抽象父类 private int i;// public abstract void play(Note n); public String what(){ return "Instrument"; } public abstract void adjust(); } class Wind extends Instrument{ public void play(Note n){ System.out.println("Wind.play() "+n); } public String what(){ return "wind"; } public void adjust(){ } }
其实能够发现和普通继承没什么区别。api
接口(interface)是一个彻底抽象的类,没有任何具体实现方法,容许建立者建立方法的方法名、参数列表以及返回类型,但没有任何方法体。接口体现的思想是:“实现了这个接口的类看起来都像这样”。而且接口具备继承的一系列特色,如向上转型等等。
接口能够加public关键字(若是要加也只能加public,不能加private和protected),不添加就是默认访问权限(包访问权限)。接口中的方法是自动是public abstract的。接口也能够包含域(即引用变量或基本变量),而且自动是static final的,而且也不能被private和protected修饰。以下例:app
package tij.interfacedemo; public class Test { public static void main(String[] args) { new Wind().play(Note.MIDDLE_A); } } enum Note{ MIDDLE_A,MIDDLE_B,MIDDLE_C; } interface Instrument{// int i=5;// void play(Note n); String what(); void adjust(); } class Wind implements Instrument{ public void play(Note n){ System.out.println("Wind.play() "+n); } public String what(){ return "wind"; } public void adjust(){ } }
这是接口的一个很好的功能
在继承中,若是一个方法接受一个类的实例做为参数,那么你能够用这个类或子类的实例当作传入参数,以下例:dom
package tij.interfacedemo; import java.util.Arrays; public class Test { static void process(Processor p, Object s) { System.out.println("Using Processor:" + p.name()); System.out.println(p.process(s)); } 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); } } class Processor { public String name() { return getClass().getSimpleName(); } Object process(Object input) { return input; } } 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 { String process(Object input) { return Arrays.toString(((String) input).split(" ")); } }
在本例中,Test.process方法能够接受一个Processor以及其子类的实例对象,而后对一个Object的对象s进行操做,根据传入的Processor不一样,进行的操做也不一样,这种方法体现了策略设计模式,这类方法包含要执行的固定部分(s),策略包含变化的部分(p)。可是在这个例子中要注意两个与本章不相关的事儿:1.应该想一想为何子类明明没有重写name方法,但输出却仍是像重写了同样。2.子类重写了process方法,但返回值不是Object而是String,重写方法必需要是与类方法的返回类型的相同或者是其子类。this
可是假如如今咱们发现了一系列滤波器类,以下:设计
class Waveform{//表明波形 private static long counter; private final long id=counter++; public String toString(){ return "Waveform"+id; } } class Filter{//滤波器 public String name(){ return getClass().getSimpleName(); } public Waveform process(Waveform input){ return input; } } class LowPass extends Filter{ double cutoff;//设定低通滤波器的滤波上限 public LowPass(double cutoff){ this.cutoff=cutoff; } public Waveform process(Waveform input){ return input; } } class HighPass extends Filter{ double cutoff;//设置高通滤波器的滤波下限 public HighPass(double cutoff){ this.cutoff=cutoff; } public Waveform process(Waveform input){ return input; } } class BandPass extends Filter{ double lowCutoff,highCutoff;//设置带通滤波器的滤波上下限 public BandPass(double lowCut,double highCut){ this.lowCutoff=lowCut; this.highCutoff=highCut; } public Waveform process(Waveform input){ return input; } }
那么若是想把各类滤波器传给Test.process方法,那这会被编译器阻止,由于process方法只接受processor类以及子类,那若是但愿运用了策略设计模式的Test.process方法仍能接受滤波器,那么首先就须要把processor改变成接口:code
interface Processor { String name() ; Object process(Object input) ; } abstract class StringProcessor implements Processor{ public String name(){ return getClass().getSimpleName(); } } class Upcase extends StringProcessor { public String process(Object input) { 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(" ")); } } class Waveform{//表明波形 private static long counter; private final long id=counter++; public String toString(){ return "Waveform"+id; } }
但接下来咱们发现,滤波器这个类是咱们找到的,咱们并不能对这么个类内的代码进行修改,如何让新的Test.process还能接受滤波器呢,因而咱们能够采用适配器设计模式,代码以下:orm
class FilterAdapter implements Processor { Filter filter; public FilterAdapter(Filter filter) { this.filter = filter; } public String name() { return filter.name(); } public Waveform process(Object input) { return filter.process((Waveform) input); } }
这样传进去这个FilterAdapter适配器就OK了对象
接口的另外一个重要的功能就是能实现多重继承
package tij.interfacedemo; public class Test { public static void main(String[] args) { Hero superman=new Hero(); superman.fight(); superman.fly(); superman.swim(); } } class ActionCharacter { public void fight() { System.out.println("fight"); } } interface CanFight { void fight(); } interface CanSwim { void swim(); } interface CanFly { void fly(); } class Hero extends ActionCharacter implements CanFight, CanSwim, CanFly { public void fly() { System.out.println("fly"); } public void swim() { System.out.println("swim"); } }
经过继承能够生成一个新的接口,以此来对原来的接口进行拓展;还能够经过继承在新接口中组合多个接口(玩的真花= =)。以下:
interface Monster { void menace(); } interface DangerousMonster extends Monster { void destroy(); } interface Lethal { void kill(); } class DragonZilla implements DangerousMonster { public void menace() {} public void destroy() {} } interface Vampire extends DangerousMonster, Lethal { void drinkBlood(); } class VeryBadVampire implements Vampire { public void destroy() {} public void menace() {} public void kill() {} public void drinkBlood() {} }
接口之间能够继承,能够多继承,能够相互拓展
在实现多重继承时,若是不一样接口有相同方法怎么办
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 int f(int i) { return 1; } public void f() {}//重载 } class C3 extends C implements I2{ public int f(int i) {//重载 return 0; } } class C4 extends C implements I3{ //能够没必要重写int f()方法,由于从C那里继承过来了,但C那里的f()必须是public的 } //class C5 extends C implements I1{ // //错误 //} //interface I4 extends I1,I3{ // //错误 //}
所以在设计接口的时候请尽可能避免这点
接口的一种经常使用的方法就是以前提到的策略设计模式,如编写一个进行某些操做的方法,而这个方法接收一些接口,就是说若是你的对象遵循个人接口那就能用。
下面的例子中使用了scanner,这个类须要接收一个readable对象,其中arg用来存储要输入的字符串的
import java.io.IOException; import java.nio.CharBuffer; import java.util.Random; import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner s = new Scanner(new RandomWords(10)); while (s.hasNext()) { System.out.println(s.next()); } } } class RandomWords implements Readable { private static Random rand = new Random(47); private static final char[] capitals = "ABCDEFGHIGKLMNOPQRST".toCharArray(); private static final char[] lowers = "ABCDEFGHIGKLMNOPQRST".toLowerCase() .toCharArray(); private static final char[] vowels = "aeiou".toCharArray(); private int count; public RandomWords(int count) { this.count = count; } public int read(CharBuffer arg) throws IOException { if (count-- == 0) { return -1; } arg.append(capitals[rand.nextInt(capitals.length)]); for (int i = 0; i < 4; i++) { arg.append(vowels[rand.nextInt(vowels.length)]); arg.append(lowers[rand.nextInt(lowers.length)]); } arg.append(" "); return 10;// Number of characters appended } }
接口的还有一个功能就是以前咱们提到过的适配器设计模式,在这里再举另外一个与scanner相关的例子。
首先假如咱们如今有一个以下的类:
class RandomDoubles{ private static Random rand =new Random(47); public double next(){ return rand.nextDouble(); } }
但愿让他做为一个readable传入给scanner,来生成随机的double类型数,这须要装饰设计模式
import java.io.IOException; import java.nio.CharBuffer; import java.util.Random; import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner s=new Scanner(new AdaptedRandomDoubles(7)); while(s.hasNext()){ System.out.println(s.next()); } } } class AdaptedRandomDoubles extends RandomDoubles implements Readable { private int count; public AdaptedRandomDoubles(int count){ this.count=count; } public int read(CharBuffer cb) throws IOException { if(count--==0){ return -1; } String result=Double.toString(this.next()); cb.append(result); return result.length(); } }
实例变量都是static final的,好告终束
推荐先看完内部类再来看这个
class t1 implements A.C,A.B{//访问不到A.D public void f() { } } class A { interface B { void f(); } public class BImp implements B { public void f() {} } private class BImp2 implements B { public void f() {} } public interface C { void f(); } class CImp implements C { public void f() {} } private interface D { void f(); } private class DImp implements D { public void f() {} } public class DImp2 implements D { public void f() {} } }
interface E{ interface G{ //默认为public void f(); } } class t2 implements E.G{ public void f() { } }
接口时实现多重继承的途径,而生成遵循某个接口的对象的典型方式就是工厂方法设计模式
package tij.interfacedemo; public class Test { public static void main(String[] args) { Factories.serviceConsumer(new Implementation1Factory()); Factories.serviceConsumer(new Implementation2Factory()); } } interface Service { void method1(); void method2(); } interface ServiceFactory { Service getService(); } class Implementation1 implements Service { Implementation1() {} public void method1() {System.out.println("Implementation1 method1");} public void method2() {System.out.println("Implementation1 method2");} } class Implementation1Factory implements ServiceFactory { public Service getService() { return new Implementation1(); } } class Implementation2 implements Service { Implementation2() {} public void method1() {System.out.println("Implementation2 method1");} public void method2() {System.out.println("Implementation2 method2");} } class Implementation2Factory implements ServiceFactory { public Service getService() { return new Implementation1(); } } class Factories{ static void serviceConsumer(ServiceFactory fact){ Service s = fact.getService(); s.method1(); s.method2(); } }
这样设计的好处就是将方法的实现与实例对象的生成分离开来,并且在使用Factories.serviceConsumer的时候不须要特定指定是哪一种Service.