面试题:能否用单个对象调用父类及不同子类的方法?
能否用单个对象调用A、B、C三个类的任意方法?
当然可以实现!虽然B和C作为A的子类,互相没有对方的属性和方法,但咱们可以通过两种靠谱的方式,搞出一个「统一入口」的对象,让它能调用这三个类的所有方法。下面给你详细讲讲:
方法一:组合(委托)模式(最推荐)
这是最直观也最易维护的方案——创建一个新类,把A、B、C的实例都作为它的成员变量,然后在这个新类里封装对应方法,内部委托给对应的实例去执行。
先给三个类加些具体方法方便演示:
class A { public void methodA() { System.out.println("调用了A类的方法"); } } class B extends A { public void methodB() { System.out.println("调用了B类的方法"); } } class C extends A { public void methodC() { System.out.println("调用了C类的方法"); } }
然后写这个统一入口类:
class UnifiedCaller { private A aInstance = new A(); private B bInstance = new B(); private C cInstance = new C(); // 委托调用A的方法 public void methodA() { aInstance.methodA(); } // 委托调用B的方法 public void methodB() { bInstance.methodB(); } // 委托调用C的方法 public void methodC() { cInstance.methodC(); } // 如果B重写了A的方法,还可以单独提供调用B版本的入口 public void methodAFromB() { bInstance.methodA(); } }
使用的时候超简单,一个对象搞定所有调用:
public class Main { public static void main(String[] args) { UnifiedCaller caller = new UnifiedCaller(); caller.methodA(); // 调用A的方法 caller.methodB(); // 调用B的方法 caller.methodC(); // 调用C的方法 } }
这种方式的好处是类型安全,编译期就能发现错误,而且逻辑清晰,后续维护起来也省心。
方法二:反射(灵活但不推荐)
如果三个类的方法特别多,手动写委托代码嫌麻烦,也可以用反射来实现。不过这种方式类型不安全,只有运行时才会发现方法名写错、参数不匹配的问题,所以只适合临时场景或者特殊需求。
我们可以写一个通用调用类,内部持有三个类的实例,通过反射自动找对应方法执行:
import java.lang.reflect.Method; class ReflectiveCaller { private A a = new A(); private B b = new B(); private C c = new C(); public void callMethod(String methodName, Object... args) throws Exception { // 优先找B类的方法 try { Method method = B.class.getMethod(methodName, getParamTypes(args)); method.invoke(b, args); return; } catch (NoSuchMethodException e) { // 找不到就找C类的方法 try { Method method = C.class.getMethod(methodName, getParamTypes(args)); method.invoke(c, args); return; } catch (NoSuchMethodException ex) { // 最后找A类的方法 Method method = A.class.getMethod(methodName, getParamTypes(args)); method.invoke(a, args); } } } // 辅助方法:获取参数的类型数组 private Class<?>[] getParamTypes(Object[] args) { if (args == null || args.length == 0) { return new Class[0]; } Class<?>[] types = new Class[args.length]; for (int i = 0; i < args.length; i++) { types[i] = args[i].getClass(); } return types; } }
使用方式如下:
public class Main { public static void main(String[] args) throws Exception { ReflectiveCaller caller = new ReflectiveCaller(); caller.callMethod("methodA"); caller.callMethod("methodB"); caller.callMethod("methodC"); } }
总结
- 优先选组合(委托)模式,安全、清晰、易维护,是日常开发的最佳实践;
- 反射方式只适合特殊场景,不建议在正式项目中大量使用;
- 至于动态代理,更适合接口而非类的场景,对于你这种类继承的情况,组合模式是最稳妥的选择。
内容的提问来源于stack exchange,提问作者Rajat Sangrame
相关产品推荐
相关产品推荐

