组合的语法是Java的有用补充吗?

时间:2008-10-31 17:21:27

标签: java inheritance compiler-construction programming-languages composition

首先,我对语言理论几乎一无所知,除了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
  • 的情况也是如此。
  • 如果组合字段共享相同的方法签名,则需要解决冲突(冲突接口如何解决这个问题?)
  • 如果你想要有几个相同类型的组合字段,那么委托给哪个字段会有明显的冲突
  • 可能还有其他100件我没想过的事情

就像我说的那样,我显然不是语言理论家,我没有花太多时间思考它,这个想法刚刚出现在我脑海里,我想知道我有多么不对劲。我觉得它会很酷。

6 个答案:

答案 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映射工具和框架提供了持久对象之间的belongsTohas-many关系,还有一些还提供了级联删除(用于组合)。我不知道有哪一个提供你正在寻找的简单的语法糖。

实际上,根据第二个想法,Groovy的MetaClass和MetaProgramming成语可以提供非常相似的东西,“自动魔法”委托。

答案 5 :(得分:-1)

在C ++中允许多重继承,我知道它有所不同,但它是在同一个思考过程中。 Java被设计为不允许多重继承,因此可以减少混淆,因此会出现错误和漏洞。

您所建议的内容与java的原则直接冲突。

话虽如此,它会很酷(不一定有用)。我是一名从C ++转换的java程序员。我喜欢能够犯下自己的错误。