示例代码:
public abstract class AbstractEvent
{
// extended by AbstractEvent subclasses, used as a lambda function interface
// (all sub-interfaces define one method)
public interface EventListener
{
}
// assigned by subclasses in a static block
protected static Class<? extends EventListener> listenerClass;
// this line obviously does not work
protected static Set<listenerClass> listeners = new HashSet<>();
public final boolean addListener(listenerClass listener)
{
return listeners.add(listener);
}
public final boolean removeListener(listenerClass listener)
{
return listeners.remove(listener);
}
}
这样的东西甚至可以在Java中使用,如果是这样,怎么样? 我在Scala中通过在抽象类中定义一个没有body的类型并在子类中定义它(并且它工作得很好)来创建它,但是我还想在Java中创建它。
关键是我想避免在AbstractEvent的所有子类中复制set代码。
答案 0 :(得分:2)
您可以使用泛型完成此操作:
public abstract class AbstractEvent<T extends EventListener>
{
public interface EventListener
{
}
protected static Set<T> listeners = new HashSet<T>();
public final boolean addListener(T listener)
{
return listeners.add(listener);
}
public final boolean removeListener(T listener)
{
return listeners.remove(listener);
}
}
编辑1: 为避免必须为每个接口创建单独的文件,您可以使用以下代码:
public static void main(String[] args)
{
EventListener anEventListener = new EventListener() {
// Any methods that you override for EventListener go in here
};
SomeEvent evt = new SomeEvent();
// You can even pass an anonymous one as a parameter.
evt.addListener(new EventListener() {
});
}
您也可以执行以下操作:
public class SomeClass
{
// This event listener is a private member of a class
private EventListener mEventListener = new EventListener() {
// Any methods that you override for EventListener go in here
};
}
答案 1 :(得分:1)
您不能覆盖静态变量(请参阅Is there a way to override class variables in Java?),并且从子类的静态块为protected static
变量赋值将无法正常工作:
class Base {
protected static String value = "Base";
public static String getValue() {
return value;
}
}
class Derived extends Base {
static {
value = "Derived";
}
}
class Main {
public static void main(String[] args) throws Exception {
// Make sure we run static initializer for Derived class
Class.forName("Derived");
System.out.println(Derived.getValue());
System.out.println(Base.getValue());
}
}
这将打印:
Derived
Derived
这可能不是你想要的。出于同样的原因,您当前的代码将listeners
设置为在不同的子类之间共享。
如果您对addListener
和removeListener
非静态感觉不错,可以选择以下内容:
// AbstractEvent.java
public abstract class AbstractEvent<T extends AbstractEvent.EventListener> {
public interface EventListener { }
protected static Map<Class<? extends AbstractEvent>, Set<EventListener>> listeners = new HashMap<>();
public final boolean addListener(T listener) {
Set<EventListener> eventListeners = listeners.getOrDefault(getClass(), new HashSet<>());
if (!listeners.containsKey(getClass())) {
listeners.put(getClass(), eventListeners);
}
return eventListeners.add(listener);
}
public final boolean removeListener(T listener) {
Set<EventListener> eventListeners = listeners.get(getClass());
if (eventListeners != null) {
return eventListeners.remove(listener);
}
return false;
}
}
// SomeEvent.java
public class SomeEvent extends AbstractEvent<SomeEvent.SomeEventListener> {
public interface SomeEventListener extends AbstractEvent.EventListener {
void someMethod();
}
}
如果您想要addListener
和removeListener
静态,那么泛型不会帮助您,因为您无法从静态方法引用类型参数。在这种情况下,我担心你将不得不在每个子类中明确声明它们。