【问题标题】:Is there a Java interface alternative with non-static fields?是否有带有非静态字段的 Java 接口替代方案?
【发布时间】:2021-04-07 12:21:13
【问题描述】:

我正在设置一个事件系统,我希望我的所有事件都扩展我创建的Event 类。但是,我还希望在任何时候都能够添加额外的 setCanceledisCanceled 方法。 这是一个例子:

public class Event {}
public interface EventCancelable {
    public default void setCanceled(boolean canceled) {...}
    public default boolean isCanceled() {...}
}

public class PlayerEvent extends Event {
    public Player player;
    public PlayerEvent(Player player) {
        this.player = player;
    }
}

public class PlayerMovementEvent extends PlayerEvent implements EventCancelable {...}

如您所见,稍后我使用了一个接口来添加方法。 问题是如果事件被取消,我必须如何存储:

public interface EventCancelable {
    Map<Object, Boolean> canceled = new HashMap<>();
    public void setCanceled(boolean canceled) {
        canceled.put(this, canceled);
    }
    public boolean isCanceled() {
        return canceled.get(this);
    }
}

注意,由于 Java 只允许静态字段,我必须创建一个映射来存储哪些事件被取消。这工作正常,但一段时间后,考虑到事件被非常频繁地调用,这将占用越来越多的内存。有没有办法在不使用界面的情况下添加可取消的功能,并且无需手动将代码放入我希望能够取消的每个事件中?我不能使用EventCancelable 类,从那时起PlayerMovementEvent 就不能同时扩展PlayerEventEventCancelable,因为我不希望所有PlayerEvents 都可以取消.

或者,Java 是否足够聪明,可以清空不再使用的额外事件的映射,因为该映射仅在接口中使用,并添加了 this 作为参数?

【问题讨论】:

  • 您不能在 Java 接口中声明非静态或非最终字段。 default 方法也不能直接访问实例字段。所以答案是否定的。任何需要声明(实例)字段的功能都需要在类中实现。
  • @StephenC 是的,我得到了那部分,我在问是否有办法在不使用界面的情况下做到这一点。我认为这是一个不?
  • 嗯,是的。使用类;例如将该功能放入您的 Event 类中。
  • 不,如果你的Map 还活着,那么它的所有内部条目也都是对Map 的强烈引用。另一方面,WeakHashMap...
  • 所以创建一个扩展PlayerEventCancellablePlayerEvent 类。但无论哪种方式,实现实例字段和引用它的方法的唯一方法是将字段声明和相应的方法放入class

标签: java class methods interface static


【解决方案1】:

您可以尝试使用WeakHashMap,寻找扩展的example here

但是,你应该知道有一些警告:

  • 当死条目将从Map 中删除时,您的控制权或知识为零

  • 这给GC 带来了额外的压力,因为它需要为这些类型的引用做额外的工作(WeakReferenceWeakHashMap 的底层)

【讨论】:

    【解决方案2】:

    默认方法不应该这样使用。他们应该提供方法的实现,这些方法可以使用接口的其他公共方法实现合理的默认值。

    尝试编写类:

    interface Cancellable {
      void cancel();
      boolean isCancelled();
    }
    class CancellableImpl implements Cancellable {
      private boolean cancelled;
      ...
    }
    
    class PlayerMovementEvent extends PlayerEvent implements Cancellable {
      private CancellableImpl cancellable = new Cancellable();
      
      public cancel() { cancellable.cancel(); }
      public isCancelled() { return cancellable.isCancelled(); }
      ...
    }
    

    只有几行额外的内容,但它使事情更容易理解。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多