Java继承中的另一个问题?

4

我有一个名为Parent.java的类和4个子类,如Child1.javaChild2.java等。

有两种方法:

  • m1()
  • m2()

还有一个字段:

  • f1

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

方法m1有共同的实现,所以我把它放在了Parent.java类中。它还引用了方法m2

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

因此我的问题如下:

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

Q2. 由于方法m2具有共同的实现,但处理的字段f1不是每个子类都具有相同的值,所以我应该将其放在父类或子类中?

Q3. 如果我应该将方法m2放在父类中,那么就会有一个问题,方法m1(具有共同的实现)引用了方法m2,这会创建任何问题吗?

5个回答

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 */ }
}

这应该允许你将尽可能多的代码推到层次结构的最后面。最少的代码重复。

编辑后修复了从子类中尝试访问私有成员的问题。改为在构造函数中设置它。


在子类中直接初始化字段还是通过在super()调用中将值作为参数传递给超类构造函数来初始化它们会更好呢? - Amit
2
我会选择将值传递给super。 - Daniel Bingham
请将父类中的上述“field”设置为protected。私有字段无法被继承,这样可以避免给他人带来困惑。 - Amit

3

我认为:

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

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);
   }
}

{...}

1

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);
    }
}

另外,您可能需要检查一下枚举是否适合您的情况。


首先,在上述问题中,我只提到了一个字段,但实际上有4个字段,所有这四个字段(均为字符串类型)都具有长且不变的值,因此根据我的想法,最好创建子类,每个子类都包含这4个字段的final static值,并将它们作为属性传递给super()调用...你认为呢?我是正确的吗?其次,请问您能否编辑您的答案,以阐明静态工厂方法。我以前没有使用过它们。 - Amit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接