《Effective Java》解读第38条:用接口模拟可扩展的枚举

第38条:用接口模拟可扩展的枚举

主要解决Java枚举的一个局限性:枚举类型不能被继承。但在某些场景下,我们希望枚举具有一定的扩展性,允许第三方添加新的枚举常量。

解决方法,通过接口来拓展枚举。

接口 + 枚举

虽然枚举类型不是可扩展的,但接口类型却是可扩展的,它是用来表示 API 中的操作的接口类型,可以定义另 个枚举类型,它实现这个接口,并用这个新类型的实例代替基本类型。

java 复制代码
// 步骤1:定义操作接口
public interface Operation {
    double apply(double x, double y);
}

// 步骤2:基础枚举实现接口
public enum BasicOperation implements Operation {
    PLUS("+") {
        public double apply(double x, double y) { return x + y; }
    },
    MINUS("-") {
        public double apply(double x, double y) { return x - y; }
    };
    
    private final String symbol;
    BasicOperation(String symbol) { this.symbol = symbol; }
}

// 步骤3:扩展枚举(新的枚举实现同一接口)
public enum ExtendedOperation implements Operation {
    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;
    ExtendedOperation(String symbol) { this.symbol = symbol; }
}

使用

java 复制代码
public class Main {
    public static void main(String[] args) {
        System.out.println(BasicOperation.PLUS.apply(1, 2));
        System.out.println(BasicOperation.MINUS.apply(1, 2));
        System.out.println(ExtendedOperation.TIMES.apply(1, 2));
        System.out.println(ExtendedOperation.DIVIDE.apply(1, 2));

        test(BasicOperation.class, 1, 2);
    }

    // 方法可以接受任何实现了Operation接口的枚举
    public static <T extends Enum<T> & Operation> void test(
            Class<T> opEnumType, double x, double y) {
        for (Operation op : opEnumType.getEnumConstants()) {
            System.out.printf("%f %s %f = %f%n",
                    x, op, y, op.apply(x, y));
        }
    }
}

也可以通过集合参数使用

java 复制代码
// 可以混合使用不同枚举类型的操作
public static void testAll(Collection<? extends Operation> operations,
        double x, double y) {
    for (Operation op : operations) {
        System.out.printf("%f %s %f = %f%n",
            x, op, y, op.apply(x, y));
    }
}

// 混合使用
testAll(Arrays.asList(BasicOperation.PLUS, 
                     ExtendedOperation.TIMES), 10, 5);

总结

虽然无法编写可扩展的枚举类型,却可以通过编写接口以及实现该接口的基础枚举类型来对它进行模拟.

相关推荐
第七页独白18 分钟前
汽车零件厂如何通过 QMS 真正落地 IATF 16949——QMS软件系统:品质检验-内审稽核-8d客诉管理:全星质量管理软件系统
java·前端·数据库
QCoding26 分钟前
Spring AI Alibaba Graph实战:从ReAct Agent到Workflow,企业AI复杂流程该如何编排?
java·人工智能
用户0942485680328 分钟前
第25章:Java虚拟线程(Project Loom)实战与调度协作
java·jvm
砚底藏山河35 分钟前
量化实战:截面因子有效性检验(IC 分析与分层回测)
java·python·金融·maven
wuminyu35 分钟前
ForkJoinPool内部WorkQueue的Lock-Free数组操作以及并发任务窃取原理剖析
java·linux·c语言·jvm·c++
Elastic 中国社区官方博客35 分钟前
使用 Lucene 搜索你的 Bean — 索引
java·大数据·数据库·elasticsearch·搜索引擎·全文检索·lucene
code2cat42 分钟前
Java进阶篇之AtomicMarkableReference:引用还在,标记已经改变
java·开发语言·cas·并发编程·逻辑删除
CappuccinoRose1 小时前
FormData数据处理
开发语言·前端·javascript·表单数据
她说彩礼65万1 小时前
C语言 堆区和栈区
java·linux·c语言
Zguigo1 小时前
【CUDA8】第一个CUDA C++ Kernel --vector add
java·开发语言·c++