Java接口之完全解藕

[来源] 达内    [编辑] 达内   [时间]2012-10-30

使用类继承的时候,方法只能针对这个系列的层次引用,其它基类的继承层级,即使是具有相同的方法也不能使用。但是接口却可以跨过这个限制,

 接口将抽象类更进了一步,它提供了完全的抽象方法,没有任何的实现方法。接口的意义是继承自这个接口的类应该看起来是这样的。任何使用这个接口的用户都知道有哪些方法可以调用,因此接口实际上是被用来定义了类之间交互的一种协议。

< p style="margin: 10px auto; padding: 0px; text-indent: 0px; line-height: 19px; color: rgb(0, 0, 0); font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 242); ">   但是,接口不仅仅是抽象类的一种极端情况,它还可以允许实现多重继承,使得类可以上塑造型到多个不同的基类型。

< p style="margin: 10px auto; padding: 0px; text-indent: 0px; line-height: 19px; color: rgb(0, 0, 0); font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 242); ">   接口里面也可以包含域,但是这些域被隐式地作为静态的和final来看待。接口中的方法应该定义为public,不过即使不显式定义为public也会默认的作为public来处理,因此当你继承一个接口,接口中的方法应该定义为public,否则为默认的包控制权限,这样会限制对接口方法的访问,编译器将不会允许。

< div style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 12px; border: 1px solid rgb(204, 204, 204); overflow: auto; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " class="cnblogs_code">
//
: interfaces/music5/Music5.java 
//

 Interfaces.

package interfaces.music5; 
import polymorphism.music.Note; 


import static
 net.mindview.util.Print.*; 
interface

 Instrument {   //
 Compile-time constant:

  int VALUE = 5; //
 static & final   //
 Cannot have method definitions:

  void play(Note n); //
 Automatically public

  void adjust(); } 
class Wind implements
 Instrument {   public
 void
 play(Note n) {     print(

this + ".play() " +
 n);   }   

public String toString() { 
return "Wind"; }   


public void adjust() { print(
this

 + ".adjust()"); } } 
class Percussion implements
 Instrument {   public 
void

 play(Note n) {     print(
this + ".play() " + n);   }   
public String toString() { 
return

 "Percussion"; }   
public

 void adjust() { print(this
 + ".adjust()"); } } 
class

 Stringed implements
 Instrument {   

public void
 play(Note n) {     print(
this

 + ".play() " + n);   }   
public

 String toString() { return
 "Stringed"; }   

public void
 adjust() { print(this
 + ".adjust()"); } } 

class Brass extends
 Wind {   public
 String toString() { return
 "Brass"; } } 

class Woodwind extends
 Wind {   public
 String toString() { return
 "Woodwind"; } } 

public class
 Music5 {   //
 Doesn’t care about type, so new types   
//

 added to the system still work right:

  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) {     
//

 Upcasting during addition to the array:

    Instrument[] orchestra = {       
new Wind(),       
new
 Percussion(),       

new
 Stringed(),       

new Brass(),       
new
 Woodwind()     };     tuneAll(orchestra);   } } 

/*
 Output: Wind.play() MIDDLE_C Percussion.play() MIDDLE_C Stringed.play() MIDDLE_C Brass.play() MIDDLE_C Woodwind.play() MIDDLE_C *///
:~
< p style="margin: 10px auto; padding: 0px; text-indent: 0px; line-height: 19px; color: rgb(0, 0, 0); font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 242); ">   不管是一般类还是抽象类还是接口,在上塑造型的使用上是没有区别的,从代码中我们可以看出来,在tune方法中,是不区分Instrument是一般类还是抽象类或者是接口的。

< p style="margin: 10px auto; padding: 0px; text-indent: 0px; line-height: 19px; color: rgb(0, 0, 0); font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 242); ">完全解藕

< p style="margin: 10px auto; padding: 0px; text-indent: 0px; line-height: 19px; color: rgb(0, 0, 0); font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 242); ">    使用类继承的时候,方法只能针对这个系列的层次引用,其它基类的继承层级,即使是具有相同的方法也不能使用。但是接口却可以跨过这个限制,看下面的代码:

< div style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 12px; border: 1px solid rgb(204, 204, 204); overflow: auto; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " class="cnblogs_code">
//
: interfaces/classprocessor/Apply.java
 
package
 interfaces.classprocessor; import
 java.util.*; 

import static
 net.mindview.util.Print.*; 
class

 Processor {   public
 String name() {     
return

 getClass().getSimpleName();   }   Object process(Object input) { 
return input; } } 


class Upcase extends
 Processor {   String process(Object input) { //
 Covariant return

    return
 ((String)input).toUpperCase();   } } class
 Downcase extends
 Processor {   String process(Object input) {     

return
 ((String)input).toLowerCase();   } } 

class Splitter extends
 Processor {   String process(Object input) {     
//

 The split() argument divides a String into pieces:

    return
 Arrays.toString(((String)input).split(" "));   } } 
public

 class Apply {   
public static
 

void process(Processor p, Object s) {     print(
"Using Processor " + p.name());     print(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);   } } /*
 Output: Using Processor Upcase DISAGREEMENT WITH BELIEFS IS BY DEFINITION INCORRECT Using Processor Downcase disagreement with beliefs is by definition incorrect Using Processor Splitter [Disagreement, with, beliefs, is, by, definition, incorrect] 
*///:~
< p style="margin: 10px auto; padding: 0px; text-indent: 0px; line-height: 19px; color: rgb(0, 0, 0); font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 242); ">   创建一个方法,根据传递参数的不同来实现不同的算法称之为策略模式,方法内包含了不同算法的相同的固定的部分,传递的策略参数里面包含了不同的算法。将策略作为参数传递到方法内部,策略里面包含了算法中需要执行的部分。下面再来看下面的代码:

< div style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 12px; border: 1px solid rgb(204, 204, 204); overflow: auto; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " class="cnblogs_code">
//
: interfaces/filters/Waveform.java

package interfaces.filters; 
public class
 Waveform {   private
 static long
 counter;   private
 final long
 id = counter++;   public
 String toString() { return
 "Waveform " + id; } } 

///:~ 
//
: interfaces/filters/Filter.java


package interfaces.filters; 
public class
 Filter {   public
 String name() {     
return

 getClass().getSimpleName();   }   
public

 Waveform process(Waveform input) { return


 input; } } ///:~ 
//
: interfaces/filters/LowPass.java


package interfaces.filters; 
public class
 LowPass extends Filter {   


double cutoff;   
public LowPass(double
 cutoff) { this.cutoff =
 cutoff; }   

public
 Waveform process(Waveform input) {     

return input; //
 Dummy processing

  } } //
/:~ //
: interfaces/filters/HighPass.java

package interfaces.filters; 
public class
 HighPass extends
 Filter {   

double cutoff;   
public HighPass(double
 cutoff) { this.cutoff =
 cutoff; }   

public
 Waveform process(Waveform input) { return

 input; } } //
/:~ //
: interfaces/filters/BandPass.java

package interfaces.filters; 
public class
 BandPass extends
 Filter {   

double
 lowCutoff, highCutoff;   

public BandPass(double
 lowCut, double
 highCut) {     lowCutoff 

= lowCut;     highCutoff =
 highCut;   }   public
 Waveform process(Waveform input) { return
 input; } } 

///:~
< p style="margin: 10px auto; padding: 0px; text-indent: 0px; line-height: 19px; color: rgb(0, 0, 0); font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 242); ">   Filter具有与Processor一样的接口,但是它并不是从Processor继承的,因此不能将Filter应用到Apply.process方法中,Apply.process和Processor的耦合过大,阻碍了process方法的重用。但是如果Processor是个接口的话,那么耦合度就足够松散,可以对process方法进行重用,看下面的修改后的代码:

< div style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 12px; border: 1px solid rgb(204, 204, 204); overflow: auto; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " class="cnblogs_code">
复制代码
//
: interfaces/interfaceprocessor/Processor.java

package
 interfaces.interfaceprocessor; public
 interface

 Processor {   String name();   Object process(Object input); } 
///:~ 
//
: interfaces/interfaceprocessor/Apply.java


package
 interfaces.interfaceprocessor; import
 static

 net.mindview.util.Print.*; 
public

 class Apply {   
public static
 void
 process(Processor p, Object s) {     print(

"Using Processor " + p.name());     print(p.process(s));   } } 
///:~
复制代码
< div style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 12px; border: 1px solid rgb(204, 204, 204); overflow: auto; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " class="cnblogs_code">
复制代码
//
: interfaces/interfaceprocessor/StringProcessor.java

package
 interfaces.interfaceprocessor; import
 java.util.*; 

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: 228 Thinking in Java Bruce Eckel 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] *///

:~
复制代码
< p style="margin: 10px auto; padding: 0px; text-indent: 0px; line-height: 19px; color: rgb(0, 0, 0); font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 242); ">   对于使用Filter的时候,可以使用适配器模式,将一种接口转换为另一种接口,如下:

< div style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 12px; border: 1px solid rgb(204, 204, 204); overflow: auto; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " class="cnblogs_code">
复制代码
//
: interfaces/interfaceprocessor/FilterProcessor.java

package
 interfaces.interfaceprocessor; import
 interfaces.filters.*

; 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);   } } 
public

 class FilterProcessor {   
public static
 void
 main(String[] args) {     Waveform w 

= new
 Waveform();     Apply.process(

new FilterAdapter(new
 LowPass(1.0)), w);     Apply.process(
new

 FilterAdapter(new HighPass(2.0
)), w);     Apply.process(

new FilterAdapter(new
 BandPass(3.0, 4.0)), w);   } } 
/*

 Output: Using Processor LowPass Waveform 0 Using Processor HighPass Waveform 0 Using Processor BandPass Waveform 0 
*///:~
复制代码
< p style="margin: 10px auto; padding: 0px; text-indent: 0px; line-height: 19px; color: rgb(0, 0, 0); font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 242); ">   从这里我们可以看出同一个接口可以有多种不同的实现,能够让你的代码具有更好的重用性能。

< p style="margin: 10px auto; padding: 0px; text-indent: 0px; line-height: 19px; color: rgb(0, 0, 0); font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 242); ">Java中的多重继承

< p style="margin: 10px auto; padding: 0px; text-indent: 0px; line-height: 19px; color: rgb(0, 0, 0); font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 242); ">    因为接口没有任何有意义的实现,所以接口不分配内存,这样就可以 多个接口进行组合。如果一个派生类是继承自类或者抽象类的时候,只能继承一个,如果继承自接口的话,那么可以继承自多个接口,而且在上塑造型的话可以转化为任何一个接口,但是如果是同时继承自接口和类的话,那么一定要先写类在写接口,如下:

< div style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 12px; border: 1px solid rgb(204, 204, 204); overflow: auto; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " class="cnblogs_code">
复制代码
//
: interfaces/Adventure.java //


 Multiple interfaces.

interface CanFight {   
void fight(); } 
interface CanSwim {   
void swim(); } 
interface CanFly {   
void fly(); } 
class ActionCharacter {   
public void
 fight() {} } class
 Hero extends ActionCharacter 


implements
 CanFight, CanSwim, CanFly {   

public void
 swim() {}   public
 void fly() {} } 


public class
 Adventure {   public 
static

 void
 t(CanFight x) { x.fight(); }   

public static
 void u(CanSwim x) { x.swim(); }


   public
 static void
 v(CanFly x) { x.fly(); }   
public

 static void
 w(ActionCharacter x) { x.fight(); }   
public

 static void
 main(String[] args) {     Hero h 
= new

 Hero();     t(h); //
 Treat it as a CanFight

    u(h); //
 Treat it as a CanSwim

    v(h); //
 Treat it as a CanFly

    w(h); //
 Treat it as an ActionCharacter

  } } //
/:~
复制代码

 

资源下载