java如何获取超类方法来修改子类字段

时间:2011-06-29 19:16:56

标签: java inheritance field hidden

我有两个A和B类,如下所示

public class A {
    Number x;

    public A (){
        x = 10;
    }

    public void setX(Number x){

        //do a bunch of super complicated and lengthy stuff
        // afterwards set x
        this.x = x;
    }
}

public class B extends A{
    int x;

    public B(){
        super();
    }

    public void setX(int x){
        super.setX(x);
    }

    public int getX(){
        return x;
    }
}

我的主要是

public class Main {
    public static void main(String[] args) {
        B test = new B();
        test.setX(9);
        System.out.println(test.getX());
    }
}

输出为0.我希望它是9.我意识到在这个简单的例子中我可以在B中的方法中写x = 9,但如果它是一个更复杂的方法,我不想重写已经在我的超类方法中编写的所有代码,那么我将如何实现呢?

编辑:在子类B中,我故意调用我的int变量x来隐藏超类变量x。在最终设置x之前,假设超类中的setX方法执行了大量其他操作。我希望它改为设置子类的x。这可能吗?这是一个微不足道的例子。在我的实际问题中,它要复杂得多。

编辑:实际问题是这个。我有一个名为ColorBinaryTree的类,它是BinaryTree的子类。唯一的区别是ColorBinaryTree类有一个颜色字段,所以我可以实现一个红黑树。 BinaryTree类引用父,左和右,它们都是BinaryTree对象。 ColorBinaryTree类具有相同的引用,但它们是ColorBinaryTree对象而不是BinaryTree对象。我有一堆操纵树的方法。一个例子是以下

public BinaryTree<E> root() {
    if (parent == null) return this;
    else return parent.root();
}

在我的子类中,我需要覆盖它,以便我可以执行协变返回类型并返回ColorBinaryTree对象。但是如果我可以在我的子类方法中调用超类方法那将是很好的。但似乎如果我调用超类方法,它会查看超类的父域。我想让它看一下子类的父字段。

7 个答案:

答案 0 :(得分:1)

让我们从这两个变量命名为x这一事实开始 - 就编译器而言,这是完全一致的。它不像B.x“覆盖A.x。如果你想要多态行为,你必须使用方法。

现在你可以覆盖B中的setX:

@Override
public void setX(Number x)
{
    this.x = x.intValue();
}

想要拨打super.setX()

如果你能给出一个更现实的例子,那会有所帮助 - 我会避免像这样的设计开始......

答案 1 :(得分:0)

您已在子课程中重新定义了x。取出int x声明并删除“super”。 setX方法的一部分,所以它只读:“this.x = x”。

问题的根源是,您正在更改A类中定义的x,然后提供B类中初始化为0的值。

答案 2 :(得分:0)

从子类输出private int x并在超类中设置Number变量。

答案 3 :(得分:0)

从类B中删除“x”变量。您的方法getX()将返回该类,而不是基类中的那个。

答案 4 :(得分:0)

没有自己的成员的解决方案怎么样(只要A中的x不是私有的):

public class B extends A {

  public void setX(int x){
    super.setX(x);
  }

  public int getX(){
    return x.intValue();
  }
}

在类层次结构中拥有相同的命名成员永远不是一个好的设计!

答案 5 :(得分:0)

当您使用泛型时,您使用Java 5.如何使用更具体的返回类型覆盖方法:

class BinaryTree<E> {
  public BinaryTree<E> root() {
    if (parent == null) return this;
    else return parent.root();
  }
}

class ColorBinaryTree<E> extends BinaryTree<E> {
  @Override
  public ColorBinaryTree<E> root() {
    return (ColorBinaryTree<E>)super.root();
  }
}

或者可以使用更复杂的通用解决方案:

abstract class AbstractBinaryTree<E, T extends AbstractBinaryTree<E,T>> {
  T parent;

  public T root() {
    if (parent == null) return (T)this;
    else return parent.root();
  }
}

class BinaryTree<E> extends AbstractBinaryTree<E, BinaryTree<E>>{
}

class ColorBinaryTree<E> extends AbstractBinaryTree<E, ColorBinaryTree<E> {
}

答案 6 :(得分:0)

我刚才遇到同样的问题,当然也是你的问题。

您可以做的一件事 - 重新初始化(不构建具有相同名称的新内容)parent的构造函数中的字段leftrightColorBinaryTree class,为ColorBinaryTree个对象。

如果您的类确实是BinaryTree的子类并且这些字段不是私有的或包私有的,那么这应该是可能的。

现在,这些字段将是ColorBinaryTree个对象,但仍然会被视为BinaryTree个对象,因为它们在超类(BinaryTree)中被声明为它们。为了解决这个问题,您可以在必要时将它们简单地转换为ColorBinaryTree个对象。