首先,我对语言理论几乎一无所知,除了Java,我几乎不知道任何其他语言,但我有一个想法,我觉得很酷,但我需要你们告诉我:
a:为什么它很糟糕
b:语言x多年来一直如此
c:我的思绪如何糟透
d:以上所有
这个想法会让组合与extends
的代码重用相同。
所以如果你有这样的课程:
public interface A { public void methodInA(); }
然后你有一个这样的课:
public class B { private composed A; public B() { // construct A within constructor } }
然后你就可以这样做了:
B myB = new B(); myB.methodInA();
无需在B班级中添加代表团。但你也可以像继承那样做,即:
@Overrides public void methodInA(){ // B's own delegation method }
缺点包括:
extends
就像我说的那样,我显然不是语言理论家,我没有花太多时间思考它,这个想法刚刚出现在我脑海里,我想知道我有多么不对劲。我觉得它会很酷。
答案 0 :(得分:1)
这听起来很酷,但我认为它会导致一些可怕的语言结构。显然,如果你声明同一个类的多个'组合'有一个问题,但是即使你禁止调用与多个(不同)组合类中的方法匹配的情况呢?您必须指定在主类中调用哪一个,并且您需要额外的语法。如果班上有公共成员,情况会变得更糟。
组合用于防止多重继承问题。允许这样的组合有效地允许多重继承,至少在解决调用哪种方法方面。由于使用Java做出的关键设计决定是禁止多重继承(出于好的理由),我认为不太可能将其引入Java。
答案 1 :(得分:0)
我不确定我是否认为这样做有明显的优势。我理解你的观点。现在要在A上调用一个方法,你必须使用myB.getAInstance()。methodInA(),但你要制作myB.methodInA()。
但是,如果您有多个A实例会怎样?如何解决方法调用?很多时候,组合意味着一对多关联,因此B有很多A实例。那么会发生什么?
我同意你列出的缺点。它可能只会造成太多的混乱而不是值得。
答案 2 :(得分:0)
查看某些语言中称为“Mixins”的内容,以及Perl 5 Moose OO系统中的“角色”。
答案 3 :(得分:0)
我认为如果你限制它使得一个类只能使用这个特性来组成一个类,那么它会有所帮助,并且可以避免许多令人头疼的问题。
我个人讨厌具体类的继承。我是Bloch的 Effective Java ,Favor composition over inheritence中第14项的重要支持者。我认为这样的事情会让他更容易实现他在该项目中推荐的习语。
老实说,如果你真的知道自己在做什么,我敢打赌你可以编写一个编译器注释来处理这个问题。因此,假设您有一个实现IBar接口的类Bar,您的类将如下所示:
public class Foo {
@Delegate(IBar.class)
private Bar bar;
// initialize bar via constructor or setter
}
然后在编译期间,可以使用Foo来实现IBar,并且该接口上尚未由Foo实现的任何方法最终都会生成为如下所示:
public Baz method1(Qux val) {
return bar.method1(val);
}
如上所述,您希望限制每个类只有一个字段可以使用此注释。如果多个字段有此注释,您可能想要抛出编译错误。或者,您可以找到一种方法将某种优先级模型编码为传递给它的参数。
现在我写出来似乎有点酷。也许下周我会玩弄它。如果我能解决任何问题,我会更新这个。
答案 4 :(得分:-1)
还需要考虑组合和聚合之间的区别。编译器如何知道您的意思是'is-a'还是'has -a'关系?
它们周围的一些ORM映射工具和框架提供了持久对象之间的belongsTo
或has-many
关系,还有一些还提供了级联删除(用于组合)。我不知道有哪一个提供你正在寻找的简单的语法糖。
实际上,根据第二个想法,Groovy的MetaClass和MetaProgramming成语可以提供非常相似的东西,“自动魔法”委托。
答案 5 :(得分:-1)
在C ++中允许多重继承,我知道它有所不同,但它是在同一个思考过程中。 Java被设计为不允许多重继承,因此可以减少混淆,因此会出现错误和漏洞。
您所建议的内容与java的原则直接冲突。
话虽如此,它会很酷(不一定有用)。我是一名从C ++转换的java程序员。我喜欢能够犯下自己的错误。