Effective Java 34 Emulate extensible enums with interfaces
Advantage |
Disadvantage |
|
Enum types |
Clarity Safety Ease of maintenance. |
None extensibility |
Typesafe enum pattern(Interfaces to emulate extensible enums) |
Extensibility |
No good way to enumerate all of the elements of a base type and its extension. Extensibility would complicate many aspects of the design and implementation. Implementations cannot be inherited from one enum type to another. |
Scenario
Sometimes it is desirable to let the users of an API provide their own operations, effectively extending the set of operations provided by the API.
Compelling use case for extensible enumerated type -- Operation codes/ opcodes.
Usage
- Pass a single instance of an "extension enum" anywhere a "base enum" is expected.
/**
* Demo for "34 Emulate extensible enums with interfaces".
*/
package com.effectivejava.EnumAnnotations;
/**
* @author Kaibo
*
*/
public interface Operation {
double apply(double x, double y);
}
/**
* Demo for the "34 Emulate extensible enums with interfaces".
*/
package com.effectivejava.EnumAnnotations;
import java.util.HashMap;
import java.util.Map;
/**
* @author Kaibo
*
*/
public enum BaseOperation implements Operation {
PLUS("+") {
public double apply(double x, double y) {
return x + y;
}
},
MINUS("-") {
public double apply(double x, double y) {
return x - y;
}
},
TIMES("*") {
public double apply(double x, double y) {
return x * y;
}
},
DIVIDE("/") {
public double apply(double x, double y) {
return x / y;
}
};
private final String symbol;
BaseOperation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
public abstract double apply(double x, double y);
// Implementing a fromString method on an enum type
private static final Map<String, BaseOperation> stringToEnum = new HashMap<String, BaseOperation>();
static { // Initialize map from constant name to enum constant
for (BaseOperation op : values())
stringToEnum.put(op.toString(), op);
}
// Returns BaseOperation for string, or null if string is invalid
public static BaseOperation fromString(String symbol) {
return stringToEnum.get(symbol);
}
}
- Pass in an entire extension enum type and use its elements in addition to or instead of those of the base type.
/**
* Demo for the "34 Emulate extensible enums with interfaces".
*/
package com.effectivejava.EnumAnnotations;
/**
* @author Kaibo
*
*/
public enum ExtendedOperation implements Operation {
EXP("^") {
public double apply(double x, double y) {
return Math.pow(x, y);
}
},
REMAINDER("%") {
public double apply(double x, double y) {
return x % y;
}
};
private final String symbol;
ExtendedOperation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
}
Note
- Passing the extended enums between methods.
- Bounded type token
public static void main(String[] args) {
double x = Double.parseDouble(args[0]);
double y = Double.parseDouble(args[1]);
test(ExtendedOperation.class, x, y);
}
private static <T extends Enum<T> & Operation> void test(
Class<T> opSet, double x, double y) {
for (Operation op : opSet.getEnumConstants())
System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));
}
b. Passing with Collection<? Extends Operation>
public static void main(String[] args) {
double x = Double.parseDouble(args[0]);
double y = Double.parseDouble(args[1]);
test(Arrays.asList(ExtendedOperation.values()), x, y);
}
private static void test(Collection<? extends Operation> opSet, double x, double y) {
for (Operation op : opSet)
System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));
}
2. The logic to store and retrieve the symbol associated with an operation is duplicated in BasicOperation and ExtendedOperation. In this case it doesn't matter because very little code is duplicated. If there were a larger amount of shared functionality, you could encapsulate it in a helper class or a static helper method to eliminate the code duplication.
Summary
While you cannot write an extensible enum type, you can emulate it by writing an interface to go with a basic enum type that implements the interface.
Effective Java 34 Emulate extensible enums with interfaces的更多相关文章
- Effective Java Index
Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...
- 《Effective Java》读书笔记 - 6.枚举和注解
Chapter 6 Enums and Annotations Item 30: Use enums instead of int constants Enum类型无非也是个普通的class,所以你可 ...
- Effective Java 目录
<Effective Java>目录摘抄. 我知道这看起来很糟糕.当下,自己缺少实际操作,只能暂时摘抄下目录.随着,实践的增多,慢慢填充更多的示例. Chapter 2 Creating ...
- 【Effective Java】阅读
Java写了很多年,很惭愧,直到最近才读了这本经典之作<Effective Java>,按自己的理解总结下,有些可能还不够深刻 一.Creating and Destroying Obje ...
- Effective Java 第三版——34. 使用枚举类型替代整型常量
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——38. 使用接口模拟可扩展的枚举
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版笔记(目录)
<Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时 ...
- [Effective Java]第八章 通用程序设计
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- Effective Java通俗理解(下)
Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...
随机推荐
- JavaScript之旅(二)
JavaScript之旅(二) 二.进阶知识 js的正则表达式 异常处理 调试 变量提升 表单验证 JSON javascript:void(0) JavaScript 代码规范 二.进阶知识 1. ...
- @import和link的区别
@import和link的区别 1.link语法结构 <link href="CSSurl路径" rel="stylesheet" type=&qu ...
- ASP.NET MVC 5 默认模板的JS和CSS 是怎么加载的?
当创建一个默认的mvc模板后,项目如下: 运行项目后,鼠标右键查看源码,在源码里看到头部和尾部都有js和css文件被引用,他们是怎么被添加进来的呢? 首先我们先看对应的view文件index.csht ...
- BZOJ3732 解析报告//LCA,最小生成树
3732: Network 题目描述 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的 ...
- “康园圈--互联网+校园平台“项目之sprint1总结
一.团队成员 梁植淋,官郅豪,纪焓,詹耀海 二.目前进度 在全体组员的努力下,目前完成了项目的<设计方案书>.<功能需求书>.框架搭建.项目部署文档. 并成 ...
- js页面跳转整理(转载未整理)
js方式的页面跳转1.window.location.href方式 <script language="JavaScript" type="text/java ...
- DataBase --- Intellij IDEA 14.1.4使用Java连接SQL Server教程
Java连接数据库的方法大体分为两种:正向连接和反向连接.反向连接需要编译器提供相关的插件来支持,目前主流的java IDE都支持反向连接.这里主要对正向连接做一个经验总结. 一.数据库的配置 1.新 ...
- 循序渐进开发WinForm项目(4)--Winform界面模块的集成使用
随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...
- 判断windows操作系统平台
判断当前Windows系统是win2000,winXP,winVista,win2003,win7... private static IntPtr GetSysTrayWnd() { IntPtr ...
- CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\helloiis\ceb8cab3\4db603d8\App_global.asax.gr73hi-k.dll”--“拒绝访问。 ”
我的报错页面: 我是使用的第一种方法解决的. 转至http://blog.csdn.net/zyzlywq/article/details/17916799 解决方法: 1,通常的解决方法:原因是由于 ...