Java继承的另一个问题是什么?

时间:2010-02-05 15:48:46

标签: java inheritance

我有一个 Parent.java 类和4个子类,如 Child1.java Child2.java 等等。

有两种方法

  • M1()
  • 平方米()

和一个字段

  • F1

字段 f1 具有基于子类的不同值。

方法 m1 具有通用实现,因此我将其放在 Parent.java 类中。它还指方法 m2

方法 m2 有共同的实现,但它处理字段 f1 ,这对所有子类都不同。

  

所以我的问题如下:

     

Q1。我应该将字段f1放在父类中,让所有子类继承它们并在它们自己的构造函数中初始化它们或者我应该为所有子类创建一个字段f1。

     

Q2。由于方法m2有共同的实现,但是进程字段f1对于每个子类没有相同的值,所以我应该将它放在父类或子类中。

     

Q3。如果我应该将方法m2放在父类中,那么方法m1(具有通用实现)的方法有一个问题是引用方法m2,那么会产生任何问题吗?

5 个答案:

答案 0 :(得分:3)

在我看来:

  1. f1应该在父类中并在子构造函数中初始化。这样,get和set方法只写一次。
  2. m2应该在父类中。
  3. m1也应该在父类中。不要忘记,如果方法abstract没有共同的实现但存在于所有子类中,也可以。这将允许您从父类中的其他方法调用它,尽管没有在那里定义。还要记住,在这种情况下,父类也需要是抽象的。

答案 1 :(得分:3)

如果m2的实现对于所有类都相同,则将m2和f1放在父类中。如果每个子类的特定部分可以在公共部分之后运行 - 将其分开并在调用super.m2()时将其放在子类中。在每个子类的构造函数中设置f1。

结果将如下所示:

public abstract class parent {
    private int field = 0;

    public parent(int f) {
         field = f;
    }


    public void m1() { /* m1's implementation */ }
    public void m2() { /* m2's common implementation */ }
}

public class child1 {
    public child1() {
        super(1);
    }

    @Override
    public void m2() { super.m2() /* m2's child1 implementation */ }
}

public class child2 {
    public child2() {
        super(2);
    }

    @Override
    public void m2() { super.m2() /* m2's child2 implementation */ }
}

这应该允许您尽可能地将最大量的代码推送到层次结构中。最少的代码重复。

编辑修复尝试从子类访问私有成员。更改为使用构造函数设置它。

答案 2 :(得分:2)

根据您的描述,我认为此实现没有任何问题:

public class Parent {
   private int f1;

   public Parent(int f1) {
      this.f1 = f1;
   }

   public void m1() { }
   public void m2() { 
      // do something with f1
      System.out.println(f1);
   }
}


public class Child1 extends Parent {

   private final int DEFAULT_FIELD_VALUE = 1;

   public Child1() {
      super(DEFAULT_FIELD_VALUE);
   }
}

public class Child2 extends Parent {
   public Child2(int value) {
      super(value);
   }
}

{...}

答案 3 :(得分:1)

您尝试做的事情听起来像模板方法设计模式:http://en.wikipedia.org/wiki/Template_method_pattern

我建议将f1放在父类中,并在父类中声明m2摘要(这将使类本身为抽象)。

答案 4 :(得分:0)

如果子类仅在f1的值上有所不同,那么即使创建子类也没有意义,您只需在构造函数中传递f1或使用静态工厂方法为不同的情况创建实例。例如:

public class Parent {

    private Value f1;

    private Parent(Value f1) {
        this.f1 = f1;
    }

    public static Parent makeChild1() {
          return new Parent(valueOfF1ForChild1);
    }

    public static Parent makeChild2() {
          return new Parent(valueOfF1ForChild2);
    }
}

此外,您可能想要查看枚举是否适合您的情况。