I often read about that down-casting is a bad thing, and now that I need it, I ask myself what alternatives I have in my example:
I have an Interface A
Three Classes that implement Interface A: X1, X2, X3
These classes describe the same content, but in different "formats" and processes (simply put), which is why I had to divide them.
Now I have a class as follows:
class Test {
A obj;
}
Depending on the "format", I do either obj = new X1(), obj = new X2() or obj = new X2()
.
And from now on, I have to use a lot of down-casting within this class to access the classes methods, when working with the object (aside from the methods in A). The only alternative I see, is to make a field for every possible class, of which only one is ever used. Which seems bad as well.
Any suggestions on how a better design would look like?
Thank you for any help.
EDIT: This is my scenario (simply put):
My main class is a container for certain data. One of which is a content attribute (kinda like the body of a HTTP Request). The content can be:
- plain text (two seperate strings)
- file (just the file path, md5, etc.) -> Will be loaded into an input stream later on.
- unknown (bytes) -> I can't and I actually don't have to know. The context later on will give me information about it.
For every type, I created a Class (TextContent, FileContent, UnknownContent). They implement the Interface Content that has the method getBytes(), that will return the content as a byte array.
Usage of the content:
- Creation
ContainerClass.setContent(plainText)
-> BaseInterface content = new TextContent(plainText)
ContainerClass.setFile(file)
-> BaseInterface content = new FileContent(file)
ContainerClass.setContent(someBytes)
-> BaseInterface content = new UnknownContent(someBytes)
My Container object can be saved to a json. The content object will only be saved, if it is Text or File (therefor I can't implement a toJsonObject() in the interface).
When the content is text, I want to check it for certain patterns. I do that outside of the container class with a Matcher Class (e.g.
((TextContent)container.content).getText()
-> sadly, the FileContent has no single text it could return, so I can't implement that one either). I could add a getContentAs..() method to my container class that will cast it appropriately, but I feel like I just work around the underlying issue :(