如何巧妙地克服静态属性无法被覆盖的事实?

发布于 2024-08-13 21:08:26 字数 1035 浏览 2 评论 0原文

我想实现一个应用程序,其中有各种可以解释为 XML 字符串的对象。首先,我想到制作一个接口,使每个对象实现两个方法:

public abstract Element toXML();
public abstract void fromXML(Element element);

第一个将对象信息转换为 DOM 元素,第二个将信息从 DOM 元素加载到对象。 我最终在每个子类中定义了一个静态 String 来保存元素的 TAG,因此我决定将接口转换为抽象类并赋予它更多功能:

public abstract class XmlElement implements Serializable {
     protected static Document elementGenerator;
     public String TAG = "undefined";

     static {
         try {
             elementGenerator = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        } catch (ParserConfigurationException e) {
            StateController.getInstance().addLog(
                    new Log(Log.Type.ERROR, "Couldn't load XML parser: " + e));
            System.exit(1);
        }
    }

    public abstract Element toXML();
    public abstract void fromXML(Element element);
}

元素生成器在 toXML 方法中使用来生成元素。我无法克服的这种设计的错误是 TAG 属性不能像我希望的那样成为静态的,主要是因为我不想实例化和对象每个子类只是为了知道它的标签用途。 Java 不允许重写静态属性或方法,这是克服这个问题的正确方法吗?

I want to implement an aplication where I have various Objects that can be interpreted as XML Strings. First I thought of making an interface which made each object implement two methods:

public abstract Element toXML();
public abstract void fromXML(Element element);

The first one turns the object information into the an DOM Element an the secondone loads the information to the object from a DOM element.
I ended up defining an static String in each subclass holding the TAG of the element, so I decided to turn the interface into an abstract class and give it more functionality:

public abstract class XmlElement implements Serializable {
     protected static Document elementGenerator;
     public String TAG = "undefined";

     static {
         try {
             elementGenerator = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        } catch (ParserConfigurationException e) {
            StateController.getInstance().addLog(
                    new Log(Log.Type.ERROR, "Couldn't load XML parser: " + e));
            System.exit(1);
        }
    }

    public abstract Element toXML();
    public abstract void fromXML(Element element);
}

The element generator is used in the toXML method to generate the Elements. The fault of this design that I'm unable to overcome is that the TAG attribute can't be made static as I wish it to be, mostly because I don't want to instantiate and object of each subclass just to know the TAG it uses.
Java doesn't allow to override Static attributes or methods, which is the correct way to overcome this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

野侃 2024-08-20 21:08:26

您最好按如下方式重构抽象类:

public abstract class XmlElement implements Serializable {
    protected static Document elementGenerator = createElementGenerator();

    protected static Document createElementGenerator() {
        try {
            elementGenerator = documentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        } catch (ParserConfigurationException e) {
            StateController.getInstance().addLog(new Log(Log.Type.ERROR, "Couldn't load XML parser: " + e));
            System.exit(1);
        }
    }

    public abstract Element toXML();
    public abstract void fromXML(Element element);
    protected abstract String getTag();
}

这会强制子类本身定义静态变量,并通过抽象 getTag() 方法将其返回到抽象类。我担心的一件事是,据我所知,elementGenerator 不是线程安全的,因为它在 XmlElement 的所有子类的所有实例之间共享,这可能是一个问题。

您正在做的事情似乎还存在其他设计问题,因为您只能有一个父类,带有执行繁重工作的实用程序类的接口可能是更好的解决方案。另外,我不确定您打算如何使用 TAG 变量。

You may be better off refactoring your abstract class as follows:

public abstract class XmlElement implements Serializable {
    protected static Document elementGenerator = createElementGenerator();

    protected static Document createElementGenerator() {
        try {
            elementGenerator = documentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        } catch (ParserConfigurationException e) {
            StateController.getInstance().addLog(new Log(Log.Type.ERROR, "Couldn't load XML parser: " + e));
            System.exit(1);
        }
    }

    public abstract Element toXML();
    public abstract void fromXML(Element element);
    protected abstract String getTag();
}

This forces the subclass to define a static variable itself and return it to the abstract class via the abstract getTag() method. One thing that concerns me is that the elementGenerator is not threadsafe as far as I see it as it is shared among all instances of all subclasses of XmlElement which may be an issue.

There seem to be other design issues with what you are doing since you can only have one parent class, an interface with a utility class performing the heavy lifting may be a better solution. Also, I am not sure how you planned to use the TAG variable.

撧情箌佬 2024-08-20 21:08:26

实际上,我在这里首先担心的是,您的 elementGenerator 因为它是静态的,所以将是一个单例,并且由于它将在文档生成期间维护状态,因此您将在尝试使用它的不同实例之间发生冲突。也许我错过了什么?

我也不确定您试图通过使 TAG 属性成为静态来简化操作的情况是什么。您是否可能有一堆 Class 对象(可能代表各种子类的类),您希望从中获取标签类型而不需要实例化?这看起来……很奇怪。难道您没有子类的实际实例(这样您就可以简单地拥有每个子类都需要实现的抽象 getTag() 方法吗?

My first concern here, actually, is that your elementGenerator, because it's static, will be a singleton, and since it will maintain state during document generation, you will get conflicts between different instances that are trying to use it. Perhaps I'm missing something?

I'm also not sure what the situation is that you're trying to make easier by making the TAG attribute be static. Are you likely to have a bunch of Class objects (which may represent the class of various subclasses) that you want to get the tag type from without needing to instantiate? That seems... weird. Wouldn't you have actual instances of the subclasses (such that you could simply have an abstract getTag() method that each one needs to implement?

醉城メ夜风 2024-08-20 21:08:26

怎么样:

public abstract class TaggedXmlElement implements XmlElement {
    private final String tag;

    TaggedXmlElement(String tag) {
        this.tag = tag;
    }

    public String getTag() {
        return tag;
    }
}

public final class DomXmlElement extends TaggedXmlElement {

    private static Map<String, DomXmlElement> CACHE = new ConcurrentHashMap<String, DomXmlElement>();

    private final Document generator;

    private DomXmlElement(String tag) {
        super(tag);
        try {
            generator = documentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        } catch (ParserConfigurationException e) {
            StateController.getInstance().addLog(new Log(Log.Type.ERROR, "Couldn't load XML parser: " + e));
            System.exit(1);
        }

    }

    public static DomXmlElement getInstance(String tag) {
        if(tag == null) {
            throw new IllegalArgumentException("tag::null");
        }
        if(CACHE.contains(tag)) {
            return CACHE.get(tag);
        }
        DomXmlElement element = new DomXmlElement(tag);
        CACHE.put(tag, element);
        return element;
    }

    // ... other stuff

}

How about something like:

public abstract class TaggedXmlElement implements XmlElement {
    private final String tag;

    TaggedXmlElement(String tag) {
        this.tag = tag;
    }

    public String getTag() {
        return tag;
    }
}

public final class DomXmlElement extends TaggedXmlElement {

    private static Map<String, DomXmlElement> CACHE = new ConcurrentHashMap<String, DomXmlElement>();

    private final Document generator;

    private DomXmlElement(String tag) {
        super(tag);
        try {
            generator = documentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        } catch (ParserConfigurationException e) {
            StateController.getInstance().addLog(new Log(Log.Type.ERROR, "Couldn't load XML parser: " + e));
            System.exit(1);
        }

    }

    public static DomXmlElement getInstance(String tag) {
        if(tag == null) {
            throw new IllegalArgumentException("tag::null");
        }
        if(CACHE.contains(tag)) {
            return CACHE.get(tag);
        }
        DomXmlElement element = new DomXmlElement(tag);
        CACHE.put(tag, element);
        return element;
    }

    // ... other stuff

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文