总结java的interface和abstract class

先说说interface和abstract method语法中需要注意的地方。

Interface:

1. An interface can contain fields, but these are implicitly static and final.

2. You can choose to explicitly declare the methods in an interface as public, but they are public even if you don’t say it.

3. Interface cannot define static method

 

Abstract:

1. 一个类中如果所有的方法都有实现,我们仍然可以定义这个类为abstract class

2. abstract和static不能放在一起定义方法。

 

Interface和Abstract class的实践

1. interface适合定义mixins(不知道mixin怎么翻译,它指窄接口,只定义specific contract).

java不能多重继承。如果想达到多重继承的效果,需要借助“多重实现”interface. interface的一个典型用法是定义小接口。比如Comparable。这样它的实现成本比较小,一个class比较容易mixin多个interface。

2. 如果interface不是mixin, 而是大一点的接口。

effective java, 2nd edition有精彩的阐述,对于大接口,我们往往使用skeletal implementation class. 举个例子:

   1: // Concrete implementation built atop skeletal implementation
   2: static List
   
   
    
     intArrayAsList(
    
    final 
    
    int[] a) {
   
   
   3: if (a == null)
   4: throw new NullPointerException();
   5: return new AbstractList
   
   
    
    () {
   
   
   6: public Integer get(int i) {
   7: return a[i];  // Autoboxing (Item 5)
   8: }
   9: @Override public Integer set(int i, Integer val) {
  10: int oldVal = a[i];
  11: a[i] = val;     // Auto-unboxing
  12: return oldVal;  // Autoboxing
  13: }
  14: public int size() {
  15: return a.length;
  16: }
  17: };
  18: }

new AbstractList 就是在应用Skeletal implementation. 有两个好处:

a) 它使实现接口更方便了

b) If, in a subsequent release, you want to add a new method to an abstract class, you can always add a concrete method containing a reasonable default implementation. All existing implementations of the abstract class will then provide the new method. This does not work for interfaces.

跟interface相关的还有一个话题是wrapper class,也很精彩,它是把继承转成合成的方式,应用了decorater模式的思想. 在书里的第16章介绍。

   1: // Wrapper class - uses composition in place of inheritance
   2: public class InstrumentedSet
   
    
    
    extends ForwardingSet
    
    
     
      {
    
    
   
   
   3:     private int addCount = 0;
   4:     public InstrumentedSet(Set
   
   
    
     s) {
   
   
   5:         super(s);
   6:     }
   7:     @Override public boolean add(E e) {
   8:         addCount++;
   9:         return super.add(e);
  10:     }
  11:     @Override public boolean addAll(Collection
   
   extends E> c) {
  12:         addCount += c.size();
  13:         return super.addAll(c);
  14:     }
  15:     public int getAddCount() {
  16:         return addCount;
  17:     }
  18: }
  19: // Reusable forwarding class
  20: public class ForwardingSet
   
    
    
    implements Set
    
    
     
      {
    
    
   
   
  21:     private final Set
   
   
    
     s;
   
   
  22:     public ForwardingSet(Set
   
   
    
     s) { 
    
    this.s = s; }
   
   
  23:     public void clear()               { s.clear();            }
  24:     public boolean contains(Object o) { return s.contains(o); }
  25:     public boolean isEmpty()          { return s.isEmpty();   }
  26:     public int size()                 { return s.size();      }
  27:     public Iterator
   
   
    
     iterator()     { 
    
    return s.iterator();  }
   
   
  28:     public boolean add(E e)           { return s.add(e);      }
  29:     public boolean remove(Object o)   { return s.remove(o);   }
  30:     public boolean containsAll(Collection
   
    c)
  31:                                    { return s.containsAll(c); }
  32:     public boolean addAll(Collection
   
   extends E> c)
  33:                                    { return s.addAll(c);      }
  34:     public boolean removeAll(Collection
   
    c)
  35:                                    { return s.removeAll(c);   }
  36:     public boolean retainAll(Collection
   
    c)
  37:                                    { return s.retainAll(c);   }
  38:     public Object[] toArray()          { return s.toArray();  }
  39:     public 
   
   
    
     T[] toArray(T[] a)      { 
    
    return s.toArray(a); }
   
   
  40:     @Override public boolean equals(Object o)
  41:                                        { return s.equals(o);  }
  42:     @Override public int hashCode()    { return s.hashCode(); }
  43:     @Override public String toString() { return s.toString(); }
  44: }

使用它的客户端程序:

   1: Set
   
   
    
     s = 
    
    new InstrumentedSet
    
    
     
     (
     
     new TreeSet
     
     
      
      (cmp));
     
     
    
    
   
   
   2: Set
   
   
    
     s2 = 
    
    new InstrumentedSet
    
    
     
     (
     
     new HashSet
     
     
      
      (capacity));
     
     
    
    
   
   

 

3. 人人都说 面向接口编程,很多时候矫枉过正了, 搞得接口漫天飞。interface常常是重构出来的,而不总是设计出来的。程序分层中,越是靠近底层的程序,越倾向于需要接口,越靠近顶层的程序,对接口的需求倾向于越小。如果你明知道以后不太可能提供另一套实现,提前写个接口摆那里也没啥意义,尽管定义接口的成本很低。如果你担心一旦有一天确实提供了另一套实现,重构code也不会很麻烦。只要遵守了单一职责原则和迪米特法则。迪米特法则的一种表述方式是:talk only to your immediate friends。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值