【问题标题】:Java inheritence problem: going beyond the vtableJava继承问题:超越vtable
【发布时间】:2011-08-04 15:58:53
【问题描述】:

这是场景:我有一个接口 A,100 个类 B0 ... B99 只实现 A 和 50 个类 C0、C2 ... C98 扩展 B0、B2 ... B98。

B 类使用 MySQL 数据库,在表上做各种事情。 C 类为 B 类添加了额外的逻辑(验证、特权等)。 B 类是由工具生成的,而 C 类是由程序员编写的。

客户端应用程序将使用 B 类,并且无权访问 C 类。当为 B 对象调用方法时,客户端将序列化该对象并将其连同要调用的方法名称一起发送到服务器应用程序。

服务器将接收 B 对象并将其转换为 A。但是,如果存在这样的类,则服务器希望执行 C 类中覆盖的方法,否则执行 B 中的方法。正常行为只会执行 B 中的方法。

如果没有将接收到的对象转换为 C 的巨大 SWITCH 语句,服务器如何能够做到这一点?

编辑:我是 java 新手,不知道反射可以做什么。在谷歌(thisthis)的帮助下,我解决了我的问题。我可以使用动态转换来实现我想要实现的目标。谢谢大家。

【问题讨论】:

  • 您是说您的客户会做B b = new B();,但您希望您的应用程序以某种方式将b 转换为C
  • 确实如此。服务器将以 A obj = Receive() 的形式接收对象,并以 obj.someMethod() 的形式调用该方法。服务器如何决定调用什么方法并不重要(所有类中只有少数方法实现)。如果 C 可用,我希望调用 C 的 someMethod()。

标签: java serialization inheritance virtual client-server


【解决方案1】:

这种方法对我来说听起来很奇怪。为什么不只提供命令(例如定义命令名称的字符串)并为这些命令注册命令对象?然后你只需发送命令以及一些序列化参数。

编辑:

从您的描述看来,C 对象似乎真的是 B 对象的装饰器。在这种情况下,它们不会从相应的 B 继承,而是对它进行 e 引用,然后服务器将查找 B 传递的装饰器(例如基于类或任何其他标识符),创建它们(或仅一个)传递 B 然后调用装饰器上的方法。

很像BufferedReader 装饰任何Reader

【讨论】:

  • 即使对我来说,这种方法似乎也很奇怪......也许是白痴:)?
  • 好吧,就像我说的,我只是发送两个参数(可能打包到一个传输对象中),根据一个参数选择方法,根据第二个参数选择方法的参数。
  • 抱歉回复不完整。我想补充的是:这种方法是一种让逻辑代码远离客户端并且仍然透明地处理对象的方法;函数调用看起来像客户端代码中的函数调用,即使对象会往返于服务器。
【解决方案2】:

好吧,您有一个运行时类型 B 的对象,并且您要求调用它,就好像它是 C 类型的对象一样。这不是继承的真正工作方式;除非它最初是作为 C 创建的,否则不能向下转换为 C,因为一般来说,它没有 C 的所有字段。

我猜你的 C 类不会向 B 添加任何额外的字段(如果他们这样做了,你的问题就没有意义了)。由于它们没有添加任何额外的字段,所以我可以看到将它们视为 C 是多么有意义,但没有真正好的方法来做到这一点。我会说:

  1. 为什么首先会有 B 和 C?为什么不只拥有拥有所有特权等的 B 类并使用它?
  2. 如果做不到这一点,我想你可以使用反射。编写一些通用代码,获取您的任何 B 类对象,构造一个新的相应 C 对象,并复制所有字段。

【讨论】:

  • B 类由工具生成。如果我编写额外的代码并再次运行该工具,我的工作将付诸东流。
  • 您可以使用工作流,在重新生成时,您不会覆盖现有类,而是与它们合并。如果您在类中的代码布局方面非常小心,那么合并应该很轻松。这将保留您的代码,但允许您添加新的自动生成的内容。
  • 是的,但这也会将逻辑暴露给客户端,我真的不想这样做。例如,在服务器端检查权限。代码甚至无法编译。
  • 我想你应该回到反思(建议2)。其他一些人已经提供了更多关于你如何做到这一点的细节。
【解决方案3】:

假设每个 C 类都有一个构造函数或静态 createFromSuper 来从它的父 B(或从 A)创建它...

您可以创建一个 FactoryClass 来注册所有可用的 C。您可以使用反射来获取要“替换”的 C 的父级,记住 Map/Hashtable 中的每个 B.class->C.class 映射。

然后当你收到一个 B 时,你将它传递给 Factory,如果找到映射,它将返回相同的 B 对象,或者调用构造函数/createFromSuper 返回 C。

【讨论】:

    猜你喜欢
    • 2010-11-25
    • 2010-09-24
    • 2014-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多