Put simply: I want the following code to print "sub":
Element e = new SubElement();
print(e);
...
private static void print(Element e) {
System.out.println("e");
}
private static void print(SubElement e) {
System.out.println("sub");
}
and i dont want to change print(Element e). so nothing like
private static void print(Element e) {
if (e instanceof SubElement) {
print((SubElement) e);
} else {
System.out.println("e");
}
}
what i would like to do is
print(e.getClass().cast(e));
to automatically cast it to the real subclass and force the system to enter print(SubElement e). is this somehow possible?
The overloaded method that is run is chosen at compile time so that is why the Element version is chosen rather than the SubElement version. What would seem more logical would be to have the Element or subclass contain the data that should be printed.
class Element {
public String getName() {
return "e";
}
}
class SubElement extends Element {
public String getName() {
return "sub";
}
}
and then in the print method:
private static void print(Element e) {
System.out.println(e.getName());
}
Whether this is going to make sense will depend on what the Element
class actually is and what the printed data represents.
Yes. You can use Visitor pattern . However it's suitable for stablished well-defined hierarchies, because the Visitor interface you have to define needs a method for each type.
interface ElementVisitor {
visit(Element e);
visit(SubElement se);
}
class ElementerPrinter implements ElementVisitor {
visit(Element e) { System.out.println("e"); }
visit(SubElement e) { System.out.println("sub"); }
}
class Element {
// here's the trick, Element knows that this is Element
// and childs have to implement it!
// if the parent-most class is an interface it force you to implement!
accept(ElementVisitor visitor) { visitor.visit(this); }
}
class SubElement {
// here's the trick, Element knows that this is SubElement
accept(ElementVisitor visitor) { visitor.visit(this); }
}
print()
needs to become an instance method of Element
, really. You're trying to imitate polymorphism in a hard way otherwise. If you wish to do that, you can't really avoid some series of if
statements of mappings from Class
to function objects. Why bother?
Are you able to push the difference of behaviour into the element classes?
Element e = new SubElement();
print(e);
...
private static void print(Element e) {
System.out.println(e.getMessageToPrint());
}
// no longer needed
//
//private static void print(SubElement e) {
// System.out.println("sub");
//}
This way, SubElement
can override the getMessageToPrint()
method.
Or better still:
Element e = new SubElement();
e.print();
I would choose a different approach. Either
Base Class
public class Element{}
Derived Class
public class SubElement extends Element{}
Helper Interface to print elements
public interface PrintHelper{
void print(Element element);
}
Factory to get the best PrintHelper for a given element
public class PrintHelperFactory{
private final Map<Class<? extends Element>, PrintHelper> registeredHelpers =
new HashMap<Class<? extends Element>, PrintHelper>();
// Register a PrintHelper for a given Element class.
public void registerHelper(final Class<? extends Element> clazz,
final PrintHelper helper){
this.registeredHelpers.put(clazz, helper);
}
// Get the most specific PrintHelper for a given Element.
public PrintHelper getHelperForElement(final Element element){
Class<? extends Element> clazz = element.getClass();
while(!Object.class.equals(clazz)){
if(this.registeredHelpers.containsKey(clazz)){
return this.registeredHelpers.get(clazz);
}
clazz = (Class<? extends Element>) clazz.getSuperclass();
}
return null;
}
}
Client test class, run as Java Application
public class Main{
public static void main(final String[] args){
final PrintHelperFactory factory = new PrintHelperFactory();
factory.registerHelper(Element.class, new PrintHelper(){
@Override
public void print(final Element element){
System.out.println("Element");
}
});
factory.registerHelper(SubElement.class, new PrintHelper(){
@Override
public void print(final Element element){
System.out.println("Sub Element");
}
});
// test it with an Element
final Element elem = new Element();
factory.getHelperForElement(elem).print(elem);
// test it with a sub class
final Element sub = new SubElement();
factory.getHelperForElement(sub).print(sub);
}
}
Output
Element
Sub Element
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.