问题描述
在用javafx做毕设的时候需要对形状添加上下文菜单。为了代码的封装性,我选择了新定义一个MyContextMenu继承ContextMenu。在解决在Shape这种非Controller添加ContexMenu的问题后发现,虽然我能将之前的形状对象传过来,但是我只能用两个形状的公共父类也就是作为我自己的类的初始化参数。在我的代码中的实际情况就是:我的自定义原型MyCircle和自定义MyEllipse是分别继承Circle和Ellipse的,而他们的公共父类是Shape,这里我的ContextMenu里面选用的参数为Shape的父接口Node。
这样就有一个问题,就是我无法将Node强制转换为MyCircle或者MyEllipse,所以也就无法调用他们虽然都有的方法。比如Shape里没有delete方法,我在各自的类里边都是写了delete方法的。
简化问题
其实仔细一想,把这个问题抽象化,就能够更好得看清这个问题的本质。
有一个X父类,A、B继承X,这是已有的无法修改的类。然后现在我要写一个MA, MB,分别继承A和B。可以画图为
然后我们需要在另外的类里面调用X,A,B中没有的,MA和MB内却有的方法。
解决方法一
第一时间就能想到的解决方案,就是检查传过来的参数是否是MA,是否是MB等等等。。。。这个很简单,但是,事实上我有许多的形状,这个方法就显得有些笨,就得写一堆其实一模一样的没什么用的代码,通篇的instanceof。而且,虽然不是一个优秀的程序员,但是,总得有优秀的梦想,这种代码,看着都让人难受想想也是下下策。于是思考其他的方法。
解决方法二
其实因为想到了方法一,想到了instanceof,就突然想到直接新建一个接口Y。MA,MB实现接口Y。然后在外部调用时instanceof Y, 然后将参数X强制转换成Y,调用Y.delete()。突然发现问题就这么神奇的解决。惊叹自己前面是那么得蠢。
代码示例:(这里只写一个调用处的代码)
public class C {
public C(X x) {
if (x instanceof Y) {
((Y)x).delete();
}
}
}
总结
解决问题后,往前看,发现这其实是一个很简单的java接口的应用,但是一开始并没有能够想到,自己思考以后觉得可能还是没有能够把问题给抽象出来,所以一时间没有能够联想到这个方法。吃一堑,长一智,毕设已经快接近尾声了,希望毕业以后能够尽量避免这种低级的问题吧。