Effective Java 18 Prefer interfaces to abstract classes
|
Feature |
Interface |
Abstract class |
|
Defining a type that permits multiple implementations |
Y |
Y |
|
Permitted to contain implementations. |
N |
Y |
|
The implemented class must reside the class hierarchy. |
N |
Y |
|
Single inheritance |
N |
Y |
|
Easy to evolve |
N |
Y |
Advantages of Interfaces
- Existing classes can be easily retrofitted to implement a new interface.
- Interfaces are ideal for defining mixins.
- Interfaces allow the construction of nonhierarchical type frameworks. (Composite)
public interface Singer {
AudioClip sing(Song s);
}
public interface Songwriter {
Song compose(boolean hit);
}
public interface SingerSongwriter extends Singer, Songwriter {
AudioClip strum();
void actSensitive();
}
- Interfaces enable safe, powerful functionality enhancements .
// Concrete implementation built atop skeletal implementation
static List<Integer> intArrayAsList(final int[] a) {
if (a == null)
throw new NullPointerException();
return new AbstractList<Integer>() {
public Integer get(int i) {
return a[i]; // Autoboxing (Item 05)
}
@Override public Integer set(int i, Integer val) {
int oldVal = a[i];
a[i] = val; // Auto-unboxing
return oldVal; // Autoboxing
}
public int size() {
return a.length;
}
};
}
Simulated multiple inheritance
The class implementing the interface can forward invocations of interface methods to a contained instance of a private inner class that extends the skeletal implementation.
// Skeletal Implementation
public abstract class AbstractMapEntry<K, V> implements Map.Entry<K, V> {
// Primitive operations
public abstract K getKey();
public abstract V getValue();
// Entries in modifiable maps must override this method
public V setValue(V value) {
throw new UnsupportedOperationException();
}
// Implements the general contract of Map.Entry.equals
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?, ?> arg = (Entry<?, ?>) o;
return equals(getKey(), arg.getKey())
&& equals(getValue(), arg.getValue());
}
private static boolean equals(Object o1, Object o2) {
return o1 == null ? o2 == null : o1.equals(o2);
}
// Implements the general contract of Map.Entry.hashCode
@Override
public int hashCode() {
return hashCode(getKey()) ^ hashCode(getValue());
}
private static int hashCode(Object obj) {
return obj == null ? 0 : obj.hashCode();
}
}
Note
- Because skeletal implementationsare designed for inheritance, you should follow all of the design and documentation guidelines in Item 17.
- A minor variant on the skeletal implementation is the simple implementation. It differs by being not abstract. It's just simplest possible working implementation. You can use it as it stands or subclass it as circumstances warrant.
Summary
If you export a nontrivial interface, you should strongly consider providing a skeletal implementation to go with it. Once an interface is released and widely implemented, it is almost impossible to change. The best thing to do when releasing a new interface is to have as many programmers as possible implement the interface in as many ways as possible before the interface is frozen. Finally, you should design all of your public interfaces with the utmost care and test them thoroughly by writing multiple implementations
Effective Java 18 Prefer interfaces to abstract classes的更多相关文章
- Effective Java 53 Prefer interfaces to reflection
Disadvantage of reflection You lose all the benefits of compile-time type checking, including except ...
- Effective Java 20 Prefer class hierarchies to tagged classes
Disadvantage of tagged classes 1. Verbose (each instance has unnecessary irrelevant fields). 2. Erro ...
- Effective Java 69 Prefer concurrency utilities to wait and notify
Principle Use the higher-level concurrency utilities instead of wait and notify for easiness. Use Co ...
- Effective Java 13 Minimize the accessibility of classes and members
Information hiding is important for many reasons, most of which stem from the fact that it decouples ...
- Effective Java 19 Use interfaces only to define types
Reason The constant interface pattern is a poor use of interfaces. That a class uses some constants ...
- Effective Java 35 Prefer annotations to naming patterns
Disadvantages of naming patterns Typographical errors may result in silent failures. There is no way ...
- Effective Java 68 Prefer executors and tasks to threads
Principle The general mechanism for executing tasks is the executor service. If you think in terms o ...
- Effective Java 25 Prefer lists to arrays
Difference Arrays Lists 1 Covariant Invariant 2 Reified at runtime Erased at run time 3 Runtime type ...
- Effective Java 46 Prefer for-each loops to traditional for loops
Prior to release 1.5, this was the preferred idiom for iterating over a collection: // No longer the ...
随机推荐
- 性能调优:理解Set Statistics Time输出
在性能调优:理解Set Statistics IO输出我们讨论了Set Statistics IO,还有如何帮助我们进行性能调优.这篇文章会讨论下Set Statistics Time,它会告诉我们执 ...
- TreeSet与TreeMap浅解
TreeSet与TreeMap的关系: 1.TreeSet 实际上就是用TreeMap来组织数据的,因为在TreeSet中保存了一个NavigableMap<e,Object>接口实例变量 ...
- Linux下中文显示乱码问题
Linux下中文显示乱码问题 输出编码选utf-8 然后文件本身编码也要是utf-8
- C#设计模式——迭代器模式(Iterator Pattern)
一.概述在软件开发过程中,我们可能会希望在不暴露一个集合对象内部结构的同时,可以让外部代码透明地访问其中包含的元素.迭代器模式可以解决这一问题.二.迭代器模式迭代器模式提供一种方法顺序访问一个集合对象 ...
- TCP和UDP之间的区别
TCP---传输控制协议,提供的是面向连接.可靠的字节流服务.当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据.TCP提供超时重发,丢弃重复数据,检验数据,流量控制等 ...
- 【基础】Html跨域跳转问题整理
今天遇到一个问题,是有关 跨域跳转问题,涉及到知识比较基础. 具体问题是: A站点的 PageA (Post数据)到 B站点的 PageB,PageB接受到后Redirect到B站的 PageC: ...
- Mantis 缺陷管理系统配置与安装
什么是Mantis MantisBT is a free popular web-based bugtracking system (feature list). It is written in t ...
- 在IIS7中使用ARR(Application Request Routing)反向代理虚拟目录到Nodejs站点
目标: 1.访问www.arrdemo.com/proxy 跳转到 localhost:8898的Nodejs站点 2.Nodejs站点的页面可以返回到浏览器,包括js,css,图片 3.Nodejs ...
- 重新想象 Windows 8.1 Store Apps (78) - 控件增强: ScrollViewer, FlipView, Popup
[源码下载] 重新想象 Windows 8.1 Store Apps (78) - 控件增强: ScrollViewer, FlipView, Popup 作者:webabcd 介绍重新想象 Wind ...
- C# 快速反射 IL
public class FastInvoke { public delegate object FastInvokeHandler(object target, object[] paramters ...