класс Java A расширяет класс B и переопределяет метод

public class A {
   protected ClassX a;
   public void foo() {
       operations on a;
   }
}

public class B extends A {
   private ClassY b; // ClassY extends ClassX
   @Override
   public void foo() {
       //wanna the exact same operation as A.foo(), but on b;
   } 
}

Извините за такое непонятное название. Мой вопрос: в классе B, когда я вызываю foo(), и мне нужна точно такая же операция, как у класса A для a. Как мне добиться этого и не дублировать тот же код из A? Если я оставлю foo() в классе B, будет ли это работать? Или что происходит, когда я вызываю super.foo() в foo();


person xiaofan2406    schedule 18.05.2012    source источник
comment
Do you mean that my class hierarchy is not well defined? Алекс, я удалил свой ответ. Я не прочитал вопрос четко. Пожалуйста, не обращайте внимания.   -  person jmort253    schedule 18.05.2012


Ответы (4)


Поскольку ClassY расширяет ClassX, вы можете удалить private ClassY b из класса B. Затем вы можете просто установить свой экземпляр ClassX в переменную экземпляра a. Это позволяет наследовать foo() в классе B, но при этом использовать ту же логику и переменную экземпляра.

public class A {
    protected ClassX a

    public void foo() {
        // operations on a;
    }
}

public class B extends A {
    // do something to set an instance of ClassY to a; for example...
    public void setClassY(ClassY b){
        this.a = b;
    }
}
person Jeremy    schedule 18.05.2012
comment
Это никак не повлияет на b. - person Mike Samuel; 18.05.2012
comment
@ nicholas.hauschild, ОП сказал, что это так. - person Jeremy; 18.05.2012
comment
@JeremyHeiler: это будет super.a = this.b? - person xiaofan2406; 18.05.2012
comment
@Alex, Нет. Поскольку B расширяет A, то любой экземпляр B может ссылаться на свой собственный a как this.a. Кроме того, говоря this.b, вы подразумеваете, что существует переменная экземпляра b, которой нет в моем примере. - person Jeremy; 18.05.2012

Похоже, что ClassX и ClassY будут иметь общий интерфейс (по крайней мере, если у них есть те же методы, которые вы хотите вызывать при поиске). Рассматривали ли вы возможность заставить foo() принимать объект типа общего интерфейса?

public class A {
   private ClassX a;
   protected void foo(ClassXAndClassYInheritMe anObject) {
       operations on anObject;
   }

   public void foo() {
       foo(a);
   }
}

public class B {
   private ClassY b;
   @Override
   public void foo() {
       foo(b);
   }
}
person nicholas.hauschild    schedule 18.05.2012
comment
Я думаю, что ClassXAndClassYInheritMe может быть просто ClassX, потому что ClassY расширяет ClassX. - person hoge1e3; 18.05.2012
comment
@ hoge1e3 Вы правы. Это то, чего я не видел в исходном вопросе. В любом случае, это все еще стоит, что это было бы правильным решением. - person nicholas.hauschild; 18.05.2012

Не определяйте метод foo() в B, если вам нужна та же операция, что и в A. Если вам нужна другая операция, чем A, переопределите метод foo() в B. Если вы хотите расширить метод foo() в B, чтобы он сначала выполнял операцию в A, а затем в B, а затем вызывал super.foo() в начале метода; если вы хотите, чтобы операция в A следовала за операцией в B, вызовите super.foo() в конце метода foo().

person redcurry    schedule 18.05.2012

Вы можете сделать super.foo() внутри вашего переопределенного метода.

person Tulio F.    schedule 18.05.2012
comment
будет ли это иметь операцию на a? - person xiaofan2406; 18.05.2012
comment
Конечно, когда вы вызываете super, он сначала запускает метод вашего суперкласса, в данном случае метод foo класса A. - person Tulio F.; 18.05.2012