我想知道是否可以强制通过枚举来实现接口。
我有以下界面:
public interface MobileApplication {
String name();
}
这应该通过枚举来实现,因为我需要保证名称的唯一性。 当我设计一个库时,我不能信任库用户,如果没有唯一的名称,我的库将根本无法工作。
我可以不用安全,只是想知道这是否可能。 谢谢
不幸的是你不能在编译时真正做到这一点。您可以通过要求 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> {
}
总而言之,总会有误用任何库的方法。库作者的目标是让正确使用库比错误使用库“更容易”。您无需将其设置为不可能来错误使用它。
不,不是。接口可以由任何类实现,并且您不能强迫库的用户使用枚举。
即使你可以,也无济于事,因为
如果没有唯一的名称,我的图书馆根本无法工作。
enum A implements MobileApplication { ONE } enum B implements MobileApplication { ONE } enum C implements MobileApplication { ONE }
您有三个枚举值,全部带有
name()
或
ONE
。例如,我想编写一个库类(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);
}
我知道这个答案似乎特定于我的用例,但对于许多其他想要强制通过枚举实现接口的情况来说,实现这个想法应该不难。