How to carefully overcome the fact that static attributes cannot be overridden?

I want to implement an application where I have various objects that can be interpreted as XML strings. At first I thought of creating an interface that made each object implement two methods:

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

The first converts information about the object into a DOM element, and the second transfers information to the object from the DOM element. I ended up defining a static string in each subclass containing the TAG of the element, so I decided to turn the interface into an abstract class and provide it with 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 elements. The fault of this project, which I cannot overcome, is that the TAG attribute cannot be static as I want, mainly because I do not want to instantiate and object of each subclass in order to know TAG it uses. Java does not allow overriding static attributes or methods, what is the right way to overcome this?

+4
source share
3 answers

You might be better off reorganizing 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 and return it to the abstract class using the abstract getTag () method. One thing that concerns me is that elementGenerator is not thread safe as far as I can see, as it is shared between all instances of all subclasses of XmlElement, which can be a problem.

There seems to be other design issues with what you are doing, since you can only have one parent class, and an interface with a utility class doing heavy lifting might be the best solution. Also, I'm not sure how you planned to use the TAG variable.

+6
source

My first problem is that your elementGenerator, as it is static, will be a single, and since it will maintain state during document generation, you will get conflicts between different instances that try to use it. Perhaps I missed something?

I'm also not sure what the situation is that you are trying to make it easier by making the TAG attribute static. Probably you have a bunch of class objects (which can represent a class of different subclasses) from which you want to get the tag type without creating an instance? That seems ... weird. Wouldn't you have real instances of subclasses (so you can just have an abstract getTag () method that everyone has to implement?

+3
source

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 } 
0
source

All Articles