我有一个跟随ApplContext的课程 http://codetidy.com/4498/(这是400行文件。不需要完全读取此文件。)
以下课程在课堂上延伸。
public class validatorApplContext extends ApplContext {
private static final String FAKE_FILE_NAME = "file://";
private static final String USER_MEDIUM_ALL = "all";
private static final String CSS_VERSION_3 = "css3";
private static final String PROFILE_NONE = "none";
private static final int DEFAULT_WARNING_LEVEL = 0;
public validatorApplContext(String lang) {
super(lang);
}
}
现在我有另一个返回ApplContext对象的类。
public class ApplContextFactory {
private static final String FAKE_FILE_NAME = "file://";
private static final String USER_MEDIUM_ALL = "all";
private static final String CSS_VERSION_3 = "css3";
private static final String PROFILE_NONE = "none";
private static final int DEFAULT_WARNING_LEVEL = 0;
public static ApplContext getApplContext(String lang) {
ApplContext ac = new ApplContext(lang);
ac.setWarningLevel(DEFAULT_WARNING_LEVEL);
ac.setCssVersion(CSS_VERSION_3);
ac.setProfile(PROFILE_NONE);
ac.setMedium(USER_MEDIUM_ALL);
ac.setFakeURL(FAKE_FILE_NAME);
ac.setTreatVendorExtensionsAsWarnings(true);
return ac;
}
}
当我在做
时,现在在ApplContextFactory类中ApplContext ac = new ApplContext(lang);
客户端的每件事都完美无缺。 但是当我在做什么时
ApplContext ac = new validatorApplContext(lang);
它不起作用。 看起来继承导致了一些问题。
如果您能够确定问题,请提供帮助。
感谢。
答案 0 :(得分:2)
在Java中,如果您有一个具有属性的类,那么在继承时无法覆盖,就像使用方法一样。属性的工作方式不同。
您可以添加具有相同名称的其他属性,这就是您所做的。因此,您的ApplContextFactory有两个名为FAKE_FILE_NAME的字段,一个在ApplContextFactory中定义,另一个在validatorApplContext中定义。读取哪一个不依赖于实例类型,就像使用方法一样。它仅取决于参考的类型。所以:
// an object with two FAKE_FILE_NAME attributes
validatorApplContext vac = new validatorApplContext ();
ApplContext AC= ac; // the same object, just a different variable
System.out.println(v.FAKE_FILE_NAME) // this reads from validatorApplContext
ac.FAKE_FILE_NAME = "test"; // this sets in ac, because this is the type of the variable
System.out.println(v.FAKE_FILE_NAME) // no change visible here
System.out.println(ac.FAKE_FILE_NAME) // change visible here.
您可能会说对方法的访问是动态的(使用运行时可用的信息),对属性的访问是静态的(仅使用编译期间可用的类型)。如果要使用多态,则需要使用方法。
在您的情况下,ApplContext中的所有代码都会看到FAKE_FILE_NAME的原始值,而validatorApplContext中的所有代码都会看到构造函数中设置的值。
最简单的解决方案是将getter和setter添加到两个类(非静态!),这将获取并设置所有静态字段。吸气剂将互相覆盖。但是你仍然会有两个属性副本,这似乎不是你真正想做的。
坦率地说,代码看起来有点不对劲。好像你对某些脚本语言有很大的经验,并试图用Java构建你的第一个更大的项目,遵循那些不太适合并且违背语言的做法。如果是这样的话,期待更多的问题。
答案 1 :(得分:0)
如果您的客户做了类似的事情:
ApplContext ac = ApplContextFactory.getInstance(language);
logger.log(ac.DEFAULT_WARNING_LEVEL, message);
这将获得ApplContext中定义的DEFAULT_WARNING_LEVEL的值,即使ac在运行时具有类型ValidatorApplContext也是如此。静态引用的绑定在编译时确定,ac将ApplContext作为声明的类型。