0

我有一个以下 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);

它不工作。看起来继承引起了一些问题。

如果您能够确定问题,请提供帮助。

谢谢。

4

2 回答 2

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 构建您的第一个更大的项目,遵循的做法并不真正适合并且与语言的本质背道而驰。如果是这样,预计会有更多问题。

于 2013-01-25T07:21:15.143 回答
0

如果您的客户执行以下操作:

ApplContext ac = ApplContextFactory.getInstance(language); logger.log(ac.DEFAULT_WARNING_LEVEL, message);

这将获得在 ApplContext 中定义的 DEFAULT_WARNING_LEVEL 的值,即使 ac 在运行时具有 ValidatorApplContext 类型。静态引用的绑定是在编译时确定的,并且 ac 将 ApplContext 作为声明的类型。

于 2013-01-27T08:18:33.677 回答