【问题标题】:Static methods in an abstract class抽象类中的静态方法
【发布时间】:2011-09-26 21:30:06
【问题描述】:

我想像这样定义一个抽象方法:

public abstract class Saveable {
    public Set<Field> getFieldSet();
    ...
}

getFields() 应该始终返回相同的输出,而不管对象的状态如何。但是,我不能将其声明为静态方法,因为我希望它被覆盖。现在我正在实现一个扩展Saveable 的类User,它有一些需要字段集的静态方法。显然,我无法得到它,因为我没有对象。关于允许我以静态方法获取字段的设计的任何想法?

【问题讨论】:

    标签: java oop inheritance static


    【解决方案1】:

    您可以在 Savable 中将当前方法保留为非静态和抽象,并从非静态实现中返回一个静态 Set。

    public class User extends Savable {
    
        public static Set<AField> aSet = new HashSet<AField>();
    
        @Override
        public Set<? extends Field> getFields() {
            return aSet;
        }
    }
    

    【讨论】:

      【解决方案2】:

      这是我制定的建议。但是您必须以某种方式命名派生类名称,在加载这些字段时,除了将方法声明为静态之外,别无他法。

      public abstract class Saveable {
          public static Set<? extends Field> getFields(Class<? extends Saveable> clazz) {
              return FieldsProvider.get(clazz);
          }
      }
      
      public class FieldsProvider {
          private static final Map<Class<? extends Saveable>, Set<? extends Field>> map =
              new HashMap<Class<? extends Saveable>, Set<? extends Field>>();
      
      public static void registerFields(Class<? extends Saveable> clazz, Collection<? extends Field> col) {
          Set<? extends Saveable> set = new HashSet<? extends Saveable>();
          set.addAll(col);
          map.put(clazz, set);
      }
      
      public static Set<? extends Field> getFieldSet(Class<? extends Saveable> clazz) {
          Set<? extends Field> set = map.get(clazz);
          if (set != null) {
              return set;
          }
          return Collections.emptySet();
      }
      }
      
      public class User extends Saveable {
      static {
          FieldsProvider.registerFields(User.class, new HashSet<? extends Field>... ;
      }
      
      static void someMethod() {
          Set<? extends Field> fieldsSet = getFields(User.class);
          ...
      }
      }
      

      【讨论】:

        【解决方案3】:

        一种方法是“伪造”this 引用,方法是将正确对象的实例传递给静态方法,然后对该对象调用 getFields

        另一种选择是将字段列表存储在类的静态字段中。您重写的 getFields() 实现可以返回它(或者最好是它的副本),并且您的静态方法可以直接访问它。

        我的偏好是实现后一个选项,因为它不那么笨拙(因为您永远不必新建一个其他无用的对象来传递给静态方法。)而且,它捕捉到了类的想法字段不依赖于给定的实例。

        【讨论】:

        • 鉴于您明确声明“getFields() 应始终返回相同的输出,而不管对象的状态如何”,它们引用的字段可能无论如何都应该是静态的(并且可能是最终的)。如果您绝对需要额外的分离,您可以编写一个额外的静态getFields() 方法,您可以调用非静态版本(和其他静态方法)。否则,@dlev 提供的答案可能是我的选择。
        【解决方案4】:

        扩展@dlev 的答案,您如何将字段存储在由每个类的唯一标识符键控的哈希图中。

        如果您使用的是 Spring,则可以在每个对象中注入一组字段。因此只有引用会被复制。

        【讨论】:

          【解决方案5】:

          不幸的是,继承的类不能覆盖静态方法,但它可以通过声明具有相同签名的静态方法来隐藏它。

          如果您的最终目的是在Saveable 类的另一个继承方法中使用GetFields(),这对您没有帮助,因为它将始终调用Saveable.getFields(),而不是您扩展类中的静态方法。

          【讨论】:

          • 他知道这一点,因为他说“但是,我不能将其声明为静态方法,因为我希望它被覆盖。”这不是一个有用的答案。
          • 它们是继承的,但不是虚拟 iirc。
          • @aioobe 所以如果你有SpecificSaveable extends SaveablegetFields() 是静态的,那么SpecificSaveable.getFields() 有效吗?
          • 是的,谢谢,我阅读了文档,我将更新我的答案。
          【解决方案6】:

          调用静态方法时,您将类的名称作为范围调用。

          所以实际上覆盖没有任何意义,反正你只是隐藏它。

          另外,由于同样的原因,它不能被继承,因为它属于类类型,而不是类实例。

          你能做的最好的就是在派生类中调用基类的静态方法,并且具有相同的方法名。

          【讨论】:

            猜你喜欢
            • 2012-12-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-09-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-01-10
            相关资源
            最近更新 更多