是否可以强制接口仅由枚举实现?

问题描述 投票:0回答:5

我想知道是否可以强制通过枚举来实现接口。

我有以下界面:

public interface MobileApplication {
    String name();
}

这应该通过枚举来实现,因为我需要保证名称的唯一性。 当我设计一个库时,我不能信任库用户,如果没有唯一的名称,我的库将根本无法工作。

我可以不用安全,只是想知道这是否可能。 谢谢

java enums
5个回答
19
投票

不幸的是你不能在编译时真正做到这一点。您可以通过要求 ordinal()

name()
等方法来给出
提示
,或者您可以在 runtime 中检查它。

关于“我不能信任库用户”:只要您在接口 JavaDoc 中记录了要求,任何不遵循它的人都会得到他们所付出的代价。

这与某人没有正确实现

equals()
hashCode()
完全一样:编译器不会强制执行它,但如果你破坏它,那么依赖它们的类也会破坏。

你能得到的最接近的可能是这样的:

public interface EnumInterface<E extends Enum<E>> {
}

实现如下所示:

public enum MyInterfaceImpl implements EnumInterface<MyInterfaceImpl> {
  FOO,
  BAR;
}

这只是另一个提示,因为“恶意”开发人员仍然可以构建这样的类:

class NotAnEnum implements EnumInterface<MyInterfaceImpl> {
}

总而言之,总会有误用任何库的方法。库作者的目标是让正确使用库比错误使用库“更容易”。您无需将其设置为不可能来错误使用它。


1
投票
我想知道是否可以强制接口 由枚举实现。

不,不是。接口可以由任何类实现,并且您不能强迫库的用户使用枚举。


1
投票

因此,只有当库用户希望有一些静态辅助工具来防止错误时,使用自定义 Java 编译器插件的方法才有意义。如果您决定使用 Java 插件选项,

此链接

可能会感兴趣。


1
投票
我想知道是否可以强制通过枚举来实现接口。

即使你可以,也无济于事,因为

如果没有唯一的名称,我的图书馆根本无法工作。

enum A implements MobileApplication { ONE } enum B implements MobileApplication { ONE } enum C implements MobileApplication { ONE }
您有三个枚举值,全部带有 
name()

ONE
    


1
投票

例如,我想编写一个库类(SettingsManagerBase)来一般管理我的应用程序“设置”,并希望保证唯一的键能够在代码中获取/设置这些设置。因此,我定义了我的界面(在这里,我还结合了已接受的答案中的想法以实现额外的“安全性”,但严格来说,这对于我的方法来说并不是必需的):

// Part of my settings library public interface SettingBase<E extends Enum<E>> { Object defaultValue(); // <-- Whatever interface is needed }

我的实现:

// Part of my application that uses the settings library public enum Setting implements SettingBase<Setting> { THEME, SHOW_DIALOGS, ...; @Override public Object defaultValue() { ... } // <-- Required interface implementation, probably based on constructor arguments (not shown) }

现在的关键是,我们的设置管理器库类指定它必须被赋予一个实现SettingBase的枚举(现在这是一个完全的保证):

// Part of my settings library public abstract class SettingsManagerBase<E extends Enum<E> & SettingBase<E>> { public void foo(E setting) { Object d = setting.defaultValue(); // We can safely use all methods from our interface String n = setting.name(); // We can safely use all enumeration methods, without needing to specify them manually in our interface or anything } }

设置管理器的实现可以是:

// Part of my application that uses the settings library public class SettingsManager extends SettingsManagerBase<Setting> { // If you need to override a function then E just turns into Setting public void foo(Setting setting) { ... } }

如果您需要与库类(SettingsManagerBase)中的通用枚举'E'对应的类实例,那么您可以这样做:

// Add to SettingsManagerBase protected Class<E> mEnumClass; public SettingsManagerBase(Class<E> enumClass) { mEnumClass = enumClass; // Now you can do things like call Enum.valueOf(...) } // Add to SettingsManager public SettingsManager() { super(Setting.class); }

我知道这个答案似乎特定于我的用例,但对于许多其他想要强制通过枚举实现接口的情况来说,实现这个想法应该不难。

© www.soinside.com 2019 - 2024. All rights reserved.