Как получить метод суперкласса для изменения поля подкласса - PullRequest
2 голосов
/ 29 июня 2011

У меня есть два класса 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;
    }
}

, и мой Main равен

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

Выходной сигнал равен 0. Я хочу, чтобы это было 9. Я понимаю, что вВ этом тривиальном примере я мог бы просто написать x = 9 в своем методе на B, но если бы это был более сложный метод, в котором я не хотел бы переписывать весь код, уже написанный в моем методе суперкласса, то как бы я это сделал??

РЕДАКТИРОВАТЬ: в подклассе BI я специально вызываю мою переменную int x, чтобы скрыть переменную суперкласса x.Представьте, что метод setX в суперклассе выполняет множество других действий, прежде чем, наконец, установить x.Я хочу, чтобы он установил х подкласса.Это возможно?Это тривиальный пример.В моей реальной проблеме это намного сложнее.

РЕДАКТИРОВАТЬ: реальная проблема заключается в следующем.У меня есть класс с именем ColorBinaryTree, который является подклассом BinaryTree.единственное отличие состоит в том, что у класса ColorBinaryTree есть поле для цвета, поэтому я могу реализовать красно-черное дерево.Класс BinaryTree ссылается на parent, left и right, которые являются объектами BinaryTree.Класс ColorBinaryTree имеет те же ссылки, но они являются объектами ColorBinaryTree вместо объектов BinaryTree.У меня есть куча методов, которые манипулируют деревом.Одним примером может быть следующий

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

В моем подклассе мне нужно переопределить это, чтобы я мог сделать ковариантный тип возврата и вернуть объект ColorBinaryTree.Но было бы неплохо, если бы я мог вызвать метод суперкласса внутри моего метода подкласса.Но кажется, что если я вызываю метод суперкласса, он смотрит на родительское поле суперкласса.Я хочу, чтобы он посмотрел на родительское поле подкласса.

Ответы [ 7 ]

1 голос
/ 29 июня 2011

Давайте начнем с того факта, что две переменные названы x - это полное совпадение с точки зрения компилятора. Это не похоже на B.x "переопределение A.x. Если вы хотите полиморфное поведение, вы должны использовать методы.

Теперь вы можете переопределить setX в B:

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

Вы могли бы также хотеть заставить его звонить super.setX().

Было бы полезно, если бы вы могли привести более реалистичный пример - я бы избежал такого дизайна, чтобы начать с ...

0 голосов
/ 20 сентября 2012

Я столкнулся с той же самой проблемой только сейчас, и, конечно, ваш вопрос тоже.

Одна вещь, которую вы можете сделать - это переинициализировать (НЕ создавать новые с одинаковыми именами) поля parent, left и right в конструкторе вашего класса ColorBinaryTree, чтобы они были ColorBinaryTree объектами .

Это должно быть возможно, если ваш класс действительно является подклассом BinaryTree, и эти поля не являются частными или пакетными.

Теперь эти поля будут ColorBinaryTree объектами, но все равно будут рассматриваться как BinaryTree объекты, потому что это то, что они были объявлены как в суперклассе (BinaryTree). Чтобы преодолеть это, вы можете просто преобразовать их в ColorBinaryTree объекты в случае необходимости.

0 голосов
/ 30 июня 2011

При использовании обобщений вы используете 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> {
}
0 голосов
/ 29 июня 2011

Как насчет этого решения без собственного члена (если x в A не является частным):

public class B extends A {

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

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

Никогда не бывает хорошим дизайном иметь одинаковые именованные члены в иерархии классов!

0 голосов
/ 29 июня 2011

Удалите переменную "x" из вашего класса B. Ваш метод getX () возвращает его, а не метод из базового класса.

0 голосов
/ 29 июня 2011

Вы выводите private int x из подкласса и устанавливаете переменную Number в суперклассе.

0 голосов
/ 29 июня 2011

Вы переопределили x в своем дочернем классе.Уберите объявление int x и удалите «super».часть метода setX, поэтому он просто читает: «this.x = x».

Корень вашей проблемы в том, что вы изменяете x, определенный в классе A, и затем предоставляете значение в классе B, которое былоинициализируется до 0.

...