OOP:简单的界面提取和更简洁的自动转发的任何习惯用法?

时间:2013-12-15 00:25:36

标签: java oop inheritance lisp composition


修改

尽管我在下面使用伪Java语法进行说明,但这个问题不仅限于任何一种编程语言。请随意使用您喜欢的编程语言发布成语或语言提供的机制。


当尝试通过组合而不是继承来重用现有类Old时,首先从现有类中手动创建新接口,然后在{{1}中编写转发函数是非常繁琐的。 }。如果New中有大量的公共方法,而你只需要覆盖少数公共方法,那么练习就会变得特别浪费。

忽略像Eclipse这样的IDE虽然可以帮助完成这个过程,但仍然无法减少必须阅读和维护的代码的冗长程度,因此有很多语言机制可以帮助...

  1. 通过Old运算符自动提取Old的公共方法;以及

  2. 默认情况下会将interfaceOf的所有自动生成的界面方法(例如,通过Old运算符转发到forwardsTo的组合实例,并且只提供您希望在Old中覆盖的一些方法。

  3. 一个例子:

    New

    我的问题是:

    1. 这是否可以在代码级别(例如,通过一些可重用的设计模式或习惯用法),以便结果在{{{{{{{{ 1}}和类似// A hypothetical, Java-like language class Old { public void a() { } public void b() { } public void c() { } private void d() { } protected void e() { } // ... } class New implements interfaceOf Old { public New() { // This would auto-forward all Old methods to _composed // except the ones overridden in New. Old forwardsTo _composed; } // The only method of Old that is being overridden in New. public void b() { _composed.b(); } private Old _composed; } 的类?

    2. 是否还有提供此类机制的其他语言?

    3. 编辑

      现在,我不太详细地了解这些语言,但是我希望像Lisp这样的'Lispy'语言在这里不会让人失望...因为Lisp毕竟是'可编程编程语言'(根据Paul Graham和其他人的说法)。

      编辑2

      我可能不是New的作者,或者可能不想更改其源代码,因此有效地希望将其用作黑盒子。

3 个答案:

答案 0 :(得分:1)

这可以用允许你指定全能法术方法的语言来完成(例如php中的__call())。您可以在此处捕获任何未明确覆盖的函数调用,检查它是否存在于类Old中,如果存在,只需转发该调用。

这样的事情:

public function __call($name, $args)
{
  if (method_exists($old, $name))
  {
    call_user_func([$obj, $name], $args);
  }
}

答案 1 :(得分:1)

我认为Go有这样的机制,一个struct可以嵌入来自另一个struct的方法。

看看here。这可能是你要问的第二个问题

答案 2 :(得分:1)

首先,在“OOP”(面向类)语言的上下文中回答设计问题:

如果您确实需要将Old替换为其完整界面IOld,只需使New实现IOld,就可以按照您的意愿行事,那你实际上应该使用继承。

如果IOld只需要New的一小部分,那么您应该只将该部分放入界面ICommon中,并让Old和{{1}实现它。在这种情况下,您只需将New替换为Old,其中ICommonOld都有意义。

其次,Common Lisp在这种情况下可以为你做什么?

Common Lisp与Java和其他面向类的语言截然不同。

只需几点:在Common Lisp中,对象主要用于构造和分类数据,而不是代码。您不会在这里找到“每个文件一个类”,“每个类一个文件”或“包名完全对应于目录结构”。方法不属于“类”,而是属于泛型函数,它们根据其参数的类别(具有启用无缝多次调度的良好副作用)进行调度。有多重继承。没有这样的接口。使用包进行模块化而不仅仅是组织类更强烈。导出了哪些符号(Java用语中的“public”)是按包定义的,而不是按类定义的(显然,上述内容没有意义)。

我认为你的问题要么在Common Lisp环境中完全消失,因为你的代码不会强制进入类结构,或者很自然地用多个调度和/或(可能是多个)继承来解决或表达。 / p>

至少需要一个完整的例子和周围系统的大部分才能尝试翻译成Common Lisp习语。你只是以不同的方式编写代码,尝试一些表单的一对一翻译是没有意义的。