修改
尽管我在下面使用伪Java语法进行说明,但这个问题不仅限于任何一种编程语言。请随意使用您喜欢的编程语言发布成语或语言提供的机制。
当尝试通过组合而不是继承来重用现有类Old
时,首先从现有类中手动创建新接口,然后在{{1}中编写转发函数是非常繁琐的。 }。如果New
中有大量的公共方法,而你只需要覆盖少数公共方法,那么练习就会变得特别浪费。
忽略像Eclipse这样的IDE虽然可以帮助完成这个过程,但仍然无法减少必须阅读和维护的代码的冗长程度,因此有很多语言机制可以帮助...
通过Old
运算符自动提取Old
的公共方法;以及
默认情况下会将interfaceOf
的所有自动生成的界面方法(例如,通过Old
运算符转发到forwardsTo
的组合实例,并且只提供您希望在Old
中覆盖的一些方法。
一个例子:
New
我的问题是:
这是否可以在代码级别(例如,通过一些可重用的设计模式或习惯用法),以便结果在{{{{{{{{ 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;
}
的类?
是否还有提供此类机制的其他语言?
编辑
现在,我不太详细地了解这些语言,但是我希望像Lisp这样的'Lispy'语言在这里不会让人失望...因为Lisp毕竟是'可编程编程语言'(根据Paul Graham和其他人的说法)。
编辑2
我可能不是New
的作者,或者可能不想更改其源代码,因此有效地希望将其用作黑盒子。
答案 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)
如果您确实需要将Old
替换为其完整界面IOld
,只需使New
实现IOld
,就可以按照您的意愿行事,那你实际上应该使用继承。
如果IOld
只需要New
的一小部分,那么您应该只将该部分放入界面ICommon
中,并让Old
和{{1}实现它。在这种情况下,您只需将New
替换为Old
,其中ICommon
和Old
都有意义。
Common Lisp与Java和其他面向类的语言截然不同。
只需几点:在Common Lisp中,对象主要用于构造和分类数据,而不是代码。您不会在这里找到“每个文件一个类”,“每个类一个文件”或“包名完全对应于目录结构”。方法不属于“类”,而是属于泛型函数,它们根据其参数的类别(具有启用无缝多次调度的良好副作用)进行调度。有多重继承。没有这样的接口。使用包进行模块化而不仅仅是组织类更强烈。导出了哪些符号(Java用语中的“public”)是按包定义的,而不是按类定义的(显然,上述内容没有意义)。
我认为你的问题要么在Common Lisp环境中完全消失,因为你的代码不会强制进入类结构,或者很自然地用多个调度和/或(可能是多个)继承来解决或表达。 / p>
至少需要一个完整的例子和周围系统的大部分才能尝试翻译成Common Lisp习语。你只是以不同的方式编写代码,尝试一些表单的一对一翻译是没有意义的。