简体   繁体   English

将instanceof更改为多态

[英]Change instanceof to polymorphism

How to remove the operator "instanceof" and replace it with polymorphism? 如何删除运算符“ instanceof”并将其替换为多态? Both NamedPlace and DescribedPlace are subclasses to the main class Place. NamedPlace和DescribedPlace都是主类Place的子类。

class RightClickListener extends MouseAdapter {

    @Override
    public void mouseClicked(MouseEvent mev) {           
        p = (Place) mev.getSource();

        if (mev.getModifiers() == InputEvent.BUTTON3_MASK) {
            if (p instanceof NamedPlace) {
                JOptionPane.showMessageDialog(null, p.getName() + " " + p.getPosition(), "Platsinfo: ", JOptionPane.INFORMATION_MESSAGE);
            }
            if (p instanceof DescribedPlace) {
                JOptionPane describedPane = new JOptionPane();
                describedPane.setMessage("Name: " + p.getName() + " " + p.getPosition() + "\n" + "Description: " + ((DescribedPlace) p).getDescription());
                describedPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
                JDialog dialog = describedPane.createDialog(p, "Platsinfo:");
                dialog.setVisible(true);
            }

        }

    }

}

You can give Place the abstract method and add the implementation to the subclasses. 您可以给Place抽象方法,然后将实现添加到子类中。

abstract class Place {
    // ..
    public abstract void action();
}

class NamedPlace extends Place {
    public void action() {
            JOptionPane.showMessageDialog(null, p.getName() + " " + p.getPosition(), "Platsinfo: ", JOptionPane.INFORMATION_MESSAGE);
    }
}

class DescribedPlace extends Place {
    public void action() {
            JOptionPane describedPane = new JOptionPane();
            describedPane.setMessage("Name: " + p.getName() + " " + p.getPosition() + "\n" + "Description: " + ((DescribedPlace) p).getDescription());
            describedPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
            JDialog dialog = describedPane.createDialog(p, "Platsinfo:");
            dialog.setVisible(true);
    }
}

and then use this in the listener. 然后在侦听器中使用它。

class RightClickListener extends MouseAdapter {

    @Override
    public void mouseClicked(MouseEvent mev) {           
        p = (Place) mev.getSource();

        if (mev.getModifiers() == InputEvent.BUTTON3_MASK) {
            p.action();
        }
    }
}

But, depending on what Place is exactly, that might not be a good idea (eg if it's not a GUI class). 但是,根据Place的确切位置,这可能不是一个好主意(例如,如果它不是GUI类)。

The only way would be to first add an abstract method like doTheThing() to your base class. 唯一的方法是首先向基类中添加一个抽象方法,如doTheThing()

So that you then simple call p.doTheThing() in that listener. 这样您就可以在该侦听器中简单地调用p.doTheThing()

And of course, NamedPlace implements that method to do: 当然,NamedPlace实现了该方法:

JOptionPane.showMessageDialog(null, p.getName() + " " + p.getPosition(), "Platsinfo: ", JOptionPane.INFORMATION_MESSAGE);

and the other class implements it to do 另一个类实现它

JOptionPane describedPane = new JOptionPane();
...

That technically does what you ask for, but it is also not a very elegant solution. 从技术上讲,这可以满足您的要求,但这也不是一个很好的解决方案。 As those two methods are doing really different things. 由于这两种方法的作用确实不同。

A more reasonable solution could be that you have an abstract method that returns a (formatted) string for example, that then gets added to a (uniform) message window, or something alike. 一个合理的解决方案可能是,您有一个抽象方法,该方法例如返回一个(格式化的)字符串,然后将其添加到一个(统一的)消息窗口中,或类似的方法。

The point of polymorphism is to allow doing "similar" things using a common interface. 多态性的目的是允许使用通用接口执行“相似”的操作。 It doesn't help with doing completely different things under the same hood. 在相同的环境下做完全不同的事情无济于事。

If your Place classes shouldn't be aware of the specific response implementation to a click, then you can use visitor pattern , and separate your Place hierarchy from it's response implementations. 如果您的Place类不应该知道单击的特定响应实现,则可以使用visitor pattern ,并将Place层次结构与其响应实现分开。

Then you can provide different implementationsfor different situations, and your Place classes will not grow and tightly couple with more and more situation specific code. 然后,您可以针对不同情况提供不同的实现,并且Place类将不会增长,并且会与越来越多的情况特定代码紧密结合。

To achieve that, update your parent class (I prefer to use interface) Place with additional method: 为此,请使用其他方法更新您的父类(我更喜欢使用接口) Place

public interface Place {
    void accept(Visitor visitor);
}

And implement it: 并实现它:

public final class NamedPlace {
    @Override
    public void accept(Visitor visitor) {
        visitor.visitNamedPlace(this);
    }
}

public final class DescribedPlace {
    @Override
    public void accept(Visitor visitor) {
        visitor.visitDescribedPlace(this);
    }
}

Now the visitor interface will look like this: 现在,访问者界面将如下所示:

public interface Visitor {
    void visitNamedPlace(NamedPlace place);
    void visitDescribedPlace(DescribedPlace place);

}

The visitor pattern is now ready. 访客模式现已准备就绪。 And let's use it in your example: 并在您的示例中使用它:

class RightClickListener extends MouseAdapter {

    @Override
    public void mouseClicked(MouseEvent mev) {           
        ((Place) mev.getSource()).accept(new Visitor() {
            @Override
            public void visitNamedPlace(NamedPlace p) {
                JOptionPane.showMessageDialog(null, p.getName() + " " + p.getPosition(), "Platsinfo: ", JOptionPane.INFORMATION_MESSAGE);
            }
            @Override
            public void visitDescribedPlace(DescribedPlace p) {
                JOptionPane describedPane = new JOptionPane();
                describedPane.setMessage("Name: " + p.getName() + " " + p.getPosition() + "\n" + "Description: " + ((DescribedPlace) p).getDescription());
                describedPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
                JDialog dialog = describedPane.createDialog(p, "Platsinfo:");
                dialog.setVisible(true);
            }
        });
    }
}

} }

Your choice is actually: 您的选择实际上是:

  • Either to have fixed implementation of response in your classes, and you can extend your hierarchy by adding more of them (earlier responses) 可以在类中固定实现响应,也可以通过添加更多类来扩展层次结构(较早的响应)
  • Or to have fixed hierarchy of classes, and provide dynamically implementations (visitor pattern). 或者具有固定的类层次结构,并提供动态的实现(访客模式)。

It depends on your use cases. 这取决于您的用例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM