【问题标题】:protected static member for inherited class继承类的受保护静态成员
【发布时间】:2014-01-30 12:23:42
【问题描述】:

我有几个类都继承了相同的基类,并且需要在启动时在函数中初始化一个静态属性。我是这样实现的:

public abstract class Base {
    protected static Model model;
}

public class Inherited extends Base {
    static {
        model = initializationFunction();
    }
}
public class OtherInherited extends Base {
    static {
        model = otherInitializationFunction();
    }
}
// Example of use
Base[] inheriteds = new Base[] { new Inherited(), new OtherInherited() };
for (int i = 0; i < inheriteds.length; i++)  {
     doStuff(inheriteds[i]).model; // This will always use the same model (last defined)
}

所以类在开始时初始化静态成员。但它似乎为整个基类设置了模型的值,因此所有类实际上都具有相同的模型。

我需要model 是静态的,因为它需要每个子类只存在一次。我的问题是如何为每个子类拥有一个静态模型,同时仍确保它在父类中定义(因此,如果一个类没有定义它,它在父类中定义)。

继承类中受保护的静态成员的预期行为是什么?我应该如何为每个类设置这个成员的版本,仍然是静态的(我不希望它为每个实例重复)?

【问题讨论】:

  • 静态字段属于 Base,无论您从何处访问它。
  • 这很简单——静态对象引用确实只存在一次。你为什么要把它变成静态的?
  • 如果模型绑定到子类,那么它应该在子类中声明,而不是在基类中。
  • 我需要它是静态的,因为 model 对象每个子类只需要存在一次。我的问题是每个子类有一个静态模型,同时仍然确保它在父类中定义。
  • @Malharhak 你不能那样做。您必须在每个子类中定义变量。

标签: java inheritance static polymorphism


【解决方案1】:

我的问题是如何为每个子类创建一个静态模型,同时仍然 确保它在父类中定义(所以如果一个类没有 定义它,它是在父类中定义的)。

没办法,因为,静态成员和多态,继承不能一起去

【讨论】:

  • 这是否意味着我不应该在继承的类上使用静态字段?如果我在子类中定义我的成员,那么对 Base 数组的模型进行迭代可能会出现问题(如果其中一个子类没有模型定义)
  • @Malharhak:你不能指望 Java 中静态文件/方法的多态行为
【解决方案2】:

继承不适用于静态字段(即类字段)。所以只有一个字段Base.modelInherited.model 指的是同一个字段。

【讨论】:

    【解决方案3】:

    如果您确实需要自动解析模型而不是让 devoloper 确保一致性,那么您需要自己实现整个机制,因为 Java 的任何语言功能都不会直接解决这个问题。

    其中一个选项是沿着Singleton 路线走,其中单例将是Model 工厂。不是直接访问静态字段来获取模型,而是要求相应类的工厂单例来获取它。工厂本身将继承基工厂,因此您可以通过多态获得“自动默认”行为。

    【讨论】:

      【解决方案4】:

      正如其他答案所暗示的那样,静态成员的范围是类级别而不是对象级别,简而言之,它不是继承层次结构的一部分。静态成员的类名只是一个额外的命名空间限定符。下面是关于 static 关键字的一个很好的概要:http://mindprod.com/jgloss/static.html

      至于解决您的问题,我在仍然使用静态成员的同时对此进行了破解。如果您确实必须让子类的每个实例共享相同的模型实例,同时保持与基类的某种接口兼容性,那么请考虑执行以下操作:

      public abstract class Base {
          public abstract Model getModel();
      }
      
      public class Inherited extends Base {
          static private Model model = initializationFunction();
      
          public Model getModel() {
              return model;
          }
      }
      
      public class OtherInherited extends Base {
          static private Model model = otherInitializationFunction();
      
          public Model getModel() {
              return model;
          }
      }
      

      这里涉及到静态成员的事实在界面中是隐藏的,这是一个很大的胜利。如果你达到了不使用静态成员就可以解决这个问题的地步,你的类层次结构的客户端将不会受到影响,因为访问模型根本不会暴露使用静态成员的实现细节。

      【讨论】:

        【解决方案5】:

        也许以某种方式管理模型对象:

        public abstract class TestBase {
        
            private static Map<Class, Object> modelObjects = new HashMap<>();
        
            public static void setModel(Class _class, Object model) {
                modelObjects.put(_class, model);
            }
        
            public static Object getModel(Class _class) {
                return modelObjects.get(_class);
            }
        
            public static class Inherited extends TestBase {
        
                static {
                    setModel(Inherited.class, new Object());
                }
            }
        
            public static class OtherInherited extends TestBase {
        
                static {
                    setModel(OtherInherited.class, new Object());
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2012-09-22
          • 2016-06-12
          • 2014-06-09
          • 2011-09-27
          • 2018-12-27
          • 2012-10-03
          • 2023-03-03
          • 1970-01-01
          • 2011-05-24
          相关资源
          最近更新 更多