如何存储关于一个类的静态数据

huangapple go评论59阅读模式
英文:

How to store static data about a class to

问题

想象一下我有一个这样的抽象类:

public abstract class Device {

  public Device(DeviceModel model){
    // ...
  }

  public abstract boolean isBuildable();
}

然后我有一个可能如下所示的实现:

public final class Floor extends Device {
  // ...

  @Override
  public void boolean isBuildable(){
    return false;
  }
}

在这里,每个Device子类都会返回true或false给#isBuildable()。但是每个Floor的实例始终返回false。Device的另一个实现可能返回true。这听起来像是静态数据:它不依赖于当前实例,而是依赖于Device的类型。

目前,我创建了类的实例来获取它的值,因为#isBuildable()不是静态的。但我认为这是糟糕的代码设计。

所以,我在这里尝试实现类似于创建abstract static方法的功能。我看到了这个问题,但没有太多帮助。我想强制在Device的所有子类中实现#isBuildable(这次是静态的),以便我可以调用Floor.isBuildable()或类似的其他东西。

在这里,我无法控制所有的源代码,所以无法使用反射来实现这一点。

希望你能理解这个有点奇怪的问题!

英文:

Imagine I have an abstract class like this:

public abstract class Device {

  public Device(DeviceModel model){
    // ...
  }

  public abstract boolean isBuildable();
}

Then I have an implementation of it that might look like this:

public final class Floor extends Device {
  // ...

  @Override
  public void boolean isBuildable(){
    return false;
  }
}

Here, each Device subclass returns either true or false to #isBuildable(). But each instance of Floor always returns false. Another implementation of Device may return true. That sounds like a static data : it does not depends on the current instance, but on the type of the Device.

Currently, I'm creating an instance of the class to get its value, as #isBuildable() isn't static. But I think that's poor code design.

So, what I'm trying to achieve here is like creating abstract static method. I've seen this question that doesn't help so much. I would forces the implementation of #isBuildable (this time as static) in all subclasses of Device, so that I can invoke Floor.isBuildable() or something else of the same kind.

Here I can't control all the source, so I can't use reflectivity on that.
Hope you understand this weird question !

答案1

得分: 1

如果您需要存储特定于类别(而不是特定于实例)的信息,自定义注释可能是一种选择。

这需要使用反射的函数来访问该信息片段,这在小型项目中可能会过于复杂,但在较大的框架或类似项目中应该不会有问题。

英文:

If you need to store class-specific (not instance-specific) information, custom annotations may be the way to go.

This require a function using reflection to access that piece of information, which could be overkill in a small project, but should be no problem in a larger framework or similar project.

答案2

得分: 1

在Java中,静态方法无法覆盖其他静态方法,所以你想要做的事情是不可能的。

由于Java没有真正的类型变量(用于泛型的类型变量在运行时不会保留),你仍然需要一个实例来确定要调用哪个被覆盖的静态方法。假设你有一个类"Device",它有两个子类"Floor"和"Ceiling",它们都有一个名为"foo()"的方法。由于没有运行时类型变量,"T.foo()" 是行不通的,而"Device.foo()"、"Floor.foo()"和"Ceiling.foo()"都明确指定了要调用的方法。

有一些解决方案/解决方法:

  • 通过反射调用正确的方法。你将失去任何静态类型检查。

  • 引入一个伴随的枚举或类,其中包含关于你的类型的信息。例如:

public class DeviceType {
    private final boolean buildable;

    private DeviceType(boolean buildable) {
        this.buildable = buildable;
    }

    public boolean isBuildable() {
        return buildable;
    }
}

public class Floor extends Device {
    public static final DeviceType DEVICE_TYPE = new DeviceType(false);
    // ...
}

现在你可以传递"Floor.DEVICE_TYPE"作为包含所需信息的类的一种表示方式。

英文:

In Java, static methods cannot override other static methods, so what you want to do is not possible.

Since Java has no real type variables (the type variables used for generics do not survive until run time) you would need an instance anyway to determine which overridden static method to call.
Suppose you have a class Device with two subclasses, Floor and Ceiling, all of which have a method called foo(). Since there are no run-time type variables, T.foo() cannot work, and Device.foo(), Floor.foo() and Ceiling.foo() all specify exactly which method to call.

There are a few solutions/workarounds:

  • Call the right method through reflection. You will lose any static type checking.

  • Introduce a companion enum or class which contains the information about your types. For example:

      public class DeviceType {
          private final boolean buildable;
    
          private DeviceType(boolean buildable) {
              this.buildable = buildable;
          }
    
          public boolean isBuildable() {
              return buildable;
          }
      }
    
      public class Floor extends Device {
          public static final DeviceType DEVICE_TYPE = new DeviceType(false);
          ...
      }
    

    Now you can pass around Floor.DEVICE_TYPE as a kind of representation of the class which contains the information you want.

huangapple
  • 本文由 发表于 2020年7月30日 23:16:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/63176259.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定