关于java中的虚方法的问题

发布于 2024-09-16 06:00:08 字数 591 浏览 9 评论 0原文

简而言之:我希望以下代码打印“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");
}

并且我不想更改 print(Element e)。所以

private static void print(Element e) {
    if (e instanceof SubElement) {
        print((SubElement) e);
    } else {
        System.out.println("e");
    }
}

我想做的就是

print(e.getClass().cast(e));

自动将其转换为真正的子类并强制系统输入 print(SubElement e)。这有可能吗?

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?

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

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

发布评论

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

评论(5

感情洁癖 2024-09-23 06:00:08

运行的重载方法是在编译时选择的,这就是选择 Element 版本而不是 SubElement 版本的原因。看起来更合乎逻辑的是让 Element 或子类包含应打印的数据。

class Element {

    public String getName() {
        return "e";
    }
}

class SubElement extends Element {
    public String getName() {
        return "sub";
    }
}

然后在 print 方法中:

private static void print(Element e) {
    System.out.println(e.getName());
}

这是否有意义将取决于 Element 类实际上是什么以及打印的数据表示什么。

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.

很快妥协 2024-09-23 06:00:08

是的。您可以使用访客模式。然而,它适用于已建立的定义良好的层次结构,因为您必须定义的 Visitor 接口需要每种类型都有一个方法。

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); }
}

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); }
}
小梨窩很甜 2024-09-23 06:00:08

print() 确实需要成为 Element 的实例方法。否则,您将尝试以困难的方式模仿多态性。如果您希望这样做,您实际上无法避免一系列从 Class 到函数对象的映射的 if 语句。何苦呢?

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?

一抹淡然 2024-09-23 06:00:08

您能够将行为差异推入元素类中吗?

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");
//}

这样,SubElement 就可以重写 getMessageToPrint() 方法。

或者更好的是:

Element e = new SubElement();
e.print();

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();
情归归情 2024-09-23 06:00:08

我会选择不同的方法。要么

  1. 按照其他人的建议使用多态性,扩展 Element 以添加 print() 方法(可以被子类覆盖),要么
  2. 定义一个辅助接口并使用策略和工厂模式的组合:

基类

 public class Element{}

派生类

 public class SubElement extends Element{}

打印元素的帮助器接口

public interface PrintHelper{
    void print(Element element);
}

为给定元素获取最佳 PrintHelper 的工厂

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;
    }

}

客户端测试类,作为 Java 应用程序运行< /strong>

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);

    }

}

输出

Element
Sub Element

I would choose a different approach. Either

  1. use polymorphism as suggested by others, extend Element to add a print() method (which can be overwritten by sub classes) or
  2. define a helper interface and use a combination of strategy and factory pattern:

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