继承后,行为正在发生变化

时间:2013-01-25 06:16:54

标签: java inheritance

我有一个跟随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);

它不起作用。 看起来继承导致了一些问题。

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

感谢。

2 个答案:

答案 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作为声明的类型。