覆盖抽象方法或在枚举中使用一个单一的方法? [英] Overriding abstract method or using one single method in enums?

查看:185
本文介绍了覆盖抽象方法或在枚举中使用一个单一的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下枚举,哪个更好?他们都可以使用完全相同的方式,但是他们的优势在于彼此?

Consider the below enums, which is better? Both of them can be used exactly the same way, but what are their advantages over each other?

1。覆盖抽象方法

public enum Direction {
    UP {
        @Override
        public Direction getOppposite() {
            return DOWN;
        }
        @Override
        public Direction getRotateClockwise() {
            return RIGHT;
        }
        @Override
        public Direction getRotateAnticlockwise() {
            return LEFT;
        }
    },
    /* DOWN, LEFT and RIGHT skipped */
    ;
    public abstract Direction getOppposite();
    public abstract Direction getRotateClockwise();
    public abstract Direction getRotateAnticlockwise();
}

2。使用单一方法:

public enum Orientation {
    UP, DOWN, LEFT, RIGHT;
    public Orientation getOppposite() {
        switch (this) {
        case UP:
            return DOWN;
        case DOWN:
            return UP;
        case LEFT:
            return RIGHT;
        case RIGHT:
            return LEFT;
        default:
            return null;
        }
    }
    /* getRotateClockwise and getRotateAnticlockwise skipped */
}






编辑:我真的希望看到一些很好的理由/详细的答案,具体的索赔的证据/来源。由于缺乏证据,大多数关于绩效的现有答案并不真正令人信服。


I really hope to see some well reasoned/elaborated answers, with evidences/sources to particular claims. Most existing answers regarding performance isn't really convincing due to the lack of proves.

您可以提出替代方案,但必须清楚如何更好地说明和/或说明的更糟糕,并在需要时提供证据。

You can suggest alternatives, but it have to be clear how it's better than the ones stated and/or how the stated ones is worse, and provide evidences when needed.

推荐答案

忘记表现在这个比较中;这将需要一个真正庞大的枚举,以便在两种方法之间形成有意义的性能差异。

Forget about performance in this comparison; it would take a truly massive enum for there to be a meaningful performance difference between the two methodologies.

我们将重点放在可维护性上。假设你完成了对 Direction 枚举的编码,并最终进入一个更有声望的项目。同时,另一位开发人员拥有您的旧代码的所有权,包括 Direction - 让我们称他为Jimmy。

Let's focus instead on maintainability. Suppose you finish coding your Direction enum and eventually move on to a more prestigious project. Meanwhile, another developer is given ownership of your old code including Direction - let's call him Jimmy.

,要求规定Jimmy添加了两个新方向: FORWARD BACKWARD 。吉米很累,过度劳累,不用担心会完全研究如何影响现有的功能 - 他只是这样做。让我们看看现在发生了什么:

At some point, requirements dictate that Jimmy add two new directions: FORWARD and BACKWARD. Jimmy is tired and overworked and does not bother to fully research how this would affect existing functionality - he just does it. Let's see what happens now:

1。覆盖抽象方法:

Jimmy立即获得编译器错误(实际上他可能会发现方法覆盖在枚举常量声明之下)。在任何情况下,在编译时发现问题。

Jimmy immediately gets a compiler error (actually he probably would've spotted the method overrides right below the enum constant declarations). In any case, the problem is spotted and fixed at compile time.

2。使用单一方法:

Jimmy没有得到编译器错误,甚至没有从他的IDE发出不完整的切换警告,因为您的开关已经有一个默认值 case。后来,在运行时,某段代码调用 FORWARD.getOpposite(),返回 null 。这导致意想不到的行为,并且最好 很快就会导致抛出 NullPointerException

Jimmy doesn't get a compiler error, or even an incomplete switch warning from his IDE, since your switch already has a default case. Later, at runtime, a certain piece of code calls FORWARD.getOpposite(), which returns null. This causes unexpected behavior and at best quickly causes a NullPointerException to be thrown.

让我们备份,并假装你添加了一些未来的打样:

Let's back up and pretend you added some future-proofing instead:

default:
    throw new UnsupportedOperationException("Unexpected Direction!");

即使这样,直到运行时才会发现问题。希望项目经过适当测试!

Even then the problem wouldn't be discovered until runtime. Hopefully the project is properly tested!

现在,您的方向示例很简单,因此这种情况可能会被夸大。在实践中,枚举可以像其他类一样容易地成为维护问题。在较大的较旧的代码库中,具有多个开发人员对重构的抵御力是一个合理的问题。许多人谈论优化代码,但是他们可以忘记开发时间也需要优化 - 包括编码以防止错误。

Now, your Direction example is pretty simple so this scenario might seem exaggerated. In practice though, enums can grow into a maintenance problem as easily as other classes. In a larger, older code base with multiple developers resilience to refactoring is a legitimate concern. Many people talk about optimizing code but they can forget that dev time needs to be optimized too - and that includes coding to prevent mistakes.

编辑: JLS示例§下的注释8.9.2-4 似乎同意:


常量特定的类体向常量附加行为。 [这个]模式比在基本类型中使用开关语句更安全,因为该模式排除了遗忘为新常量添加行为的可能性(因为枚举声明会导致编译时错误)。

Constant-specific class bodies attach behaviors to the constants. [This] pattern is much safer than using a switch statement in the base type... as the pattern precludes the possibility of forgetting to add a behavior for a new constant (since the enum declaration would cause a compile-time error).

这篇关于覆盖抽象方法或在枚举中使用一个单一的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆