12

我有这样的课:

MyClass extends MyAbstractClass implement myInterface1, myInterface2,...

我需要创建带有附加字段的新类:

MyType1 field1;
MyType2 field2;
.......

似乎正确创建了将包装 MyClass 的新类,例如:

MyWrapClass {
 MyClass myClass=new MyClass(...);
 MyType1 field1;
 MyType2 field2;
 .....

但是 MyWrapClass 用作 myInterface1 或 myInterface2 类型!

所以问题是:我应该在 MyWrapClass 中声明接口 myInterface1、myInterface2 所需的所有方法吗?还是以另一种方式存在?谢谢。

4

5 回答 5

16

基本上,有两种方法。第一个是扩展基类:

public class MySubClass extends MyClass {
     private MyType1 field1;
     private MyType2 field2;
....

第二种选择是使用组合:

public class MySubClass implements myInterface1, myInterface2 {
      private MyClass delegate;
      private MyType1 field1;
      private MyType2 field2;

      // for all methods in myInterface1, myInterface2
      public SomeType method1() {
         return delegate.method1();
      }
      ... 
}

许多 Java 大师推荐第二个选项:

乔什·布洛赫 (Josh Bloch) 的《有效 Java 第 2 版》一书

  • 第 16 条:优先组合而不是继承
  • 第 17 项:设计和文件继承或禁止继承

好的面向对象设计不是自由扩展现有的类。你的第一直觉应该是作曲。

另见http://en.wikipedia.org/wiki/Composition_over_inheritance

组合优于继承可以简化业务域类的初始设计,并在长期内提供更稳定的业务域。与继承相比,它的优势在于对利益的隔离比由后代类的层次结构描述的更彻底。此外,继承模型通常是在定义业务域类时设计的,以便理解问题域中的信息,并且不一定反映各种系统对象的真实关系。

PS:一些现代 IDE 支持自动生成合成代码

于 2012-04-04T16:10:43.810 回答
3

不要包装,只是子类:

class MySubClass extends MyClass {
    MyType1 field1;
    MyType2 field2;
    ...
于 2012-04-04T15:50:44.070 回答
2

假设您不能扩展 MyClass,那么没有其他方法可以拥有 MyWrapClass 并像 MyClass 一样使用它。例如,我碰巧必须实现 Map 才能包装实际地图。它具有许多功能,并且必须实现您打算使用的每一个功能。这里有一点余地,如果你不打算将它传递给你没有编写的函数,你可以添加所有必需的方法并只实现你需要的方法。尽管通常情况并非如此。

或者,您可以编写一个虚拟类,该类实现调用包装器的接口的所有方法。然后你可以用你自己的实现覆盖这个类,允许你回收一个包装类,而不必每次都实现所有的方法。

于 2012-04-04T15:58:51.183 回答
2

听起来代理可能会解决问题: http: //docs.oracle.com/javase/1.5.0/docs/guide/reflection/proxy.html

请注意,它很慢(使用反射)

于 2012-04-04T16:03:09.867 回答
2

假设您不能扩展 MyClass,并且您希望能够使用 MyWrapClass 作为类型 myInterface1 或 myInterface2。您可以执行以下操作:

MyWrapClass implement myInterface1, myInterface2,...{
   MyClass myClass=new MyClass(...);
   MyType1 field1;
   MyType2 field2;

   methodInInterface1 () {
      myClass.methodInInterface1 ()
   }

   ....

您将 myInterface1 和 myInterface2 中的所有方法实现委托给 MyClass。我相信这被称为作曲。

于 2012-04-04T16:13:27.680 回答