#java #polymorphism #overriding #decorator
#java #полиморфизм #переопределение #декоратор
Вопрос:
Редактировать: похоже, что моя проблема исходит откуда-то совсем из другого места. Если вы еще не прочитали остальную часть этого раздела, у меня есть a class A
, a class B
extending class A
и a class BDecorator
extending class B
. Я думал, что не смогу переопределить определенную функцию class B
из моего декоратора, но после нескольких дней тестирования и испытаний, похоже, моя проблема связана с тем, как я создаю потоки. class A
реализует Runnable и имеет функцию listen()
, создающую поток и вызывающую start()
. Я создаю поток с аргументом this
. Это важно, потому что в определенное время поток создается, this
будет иметь тип class B
.
new BDecorator(new B());
// ^ The thread is created with the creation of this object, before it can be passed as an argument to BDecorator
Поскольку поток является of class B
, он вызовет foo()
из B object
используемого для его создания.
Хотя я бы не сказал, что эта проблема решена, теперь это совершенно другая проблема и не имеет ничего общего с полиморфизмом. Спасибо @akuzminykh, @dreamcrash и @Itay Dumay за помощь в решении этой проблемы, а также за правильное форматирование этого сообщения.
У меня есть аннотация class A
, реализующая Runnable. A
выполняет следующие действия в run()
методе (сокращенный):
final public void run() {
try {
this.foo(message);
}
//...
}
Class A
также имеет следующую функцию:
protected abstract void foo(String message);
Первая итерация декоратора: переопределение функции foo.
Затем я создал класс B, который не является абстрактным, делая это:
public class B extends A {
// Constructors and getters/setters go here
protected void foo(String message) {
System.out.println(message);
}
}
Этот код работает нормально. С тех пор я решил добавить функциональные возможности B
, которые не изменили бы способ работы всего приложения, создав декоратор.
public class BDecorator extends B {
B decoratedB;
public BDecorator(B b) {
this.decoratedB = b;
}
@Override
protected void foo(String message) {
this.decoratedB.foo("Testing a foo decorator: " message);
}
}
Короче говоря, я пытаюсь переопределить метод от родителя, который уже реализовал указанный метод от своего собственного родителя (метод переопределения внука от родителя, метод реализации от дедушки и бабушки).
Вторая итерация декоратора: переопределение новой функции bar, созданной в B
.
Странно то, что у меня также есть метод, написанный B
примерно так:
public class B extends A {
// Constructors and getters/setters go here
protected void foo(String message) {
System.out.println(message);
}
protected void bar(String message) {
System.out.println(message);
}
}
bar
нигде не существует class A
.
Я могу подтвердить, что программа действительно вызовет BDecorator::bar()
со следующим переопределением (когда я устанавливаю точки останова):
public class BDecorator extends B {
B decoratedB;
public BDecorator(B b) {
this.decoratedB = b;
}
@Override
protected void foo(String message) {
this.decoratedB.foo("Testing a foo decorator: " message);
}
// This method wasn't in A. It was only present in B, and for some reasons it gets called.
@Override
protected void bar(String message) {
this.decoratedB.bar("Testing a bar decorator: " message);
}
}
Вот что происходит в моем основном:
B firstTestSubject = new BDecorator(new B(...));
BDecorator secondTestSubject = new BDecorator(new B(...));
// Let's test both foo functions
firstTestSubject.foo("Hello world!");
secondTestSubject.foo("Hello world!");
// Now let's test both bar functions
firstTestSubject.bar("Goodbye world!");
secondTestSubject.bar("Goodbye world!)";
Вывод:
> Hello world!
> Hello world!
> Testing a bar decorator: Goodbye world!
> Testing a bar decorator: Goodbye world!
Вопрос в том, почему foo override
from BDecorator
никогда не вызывается?
Комментарии:
1. Привет, не могли бы вы также проголосовать за ответ i.stack.imgur.com/Y7YCv.png 🙂
Ответ №1:
Вопрос в том, почему
foo
переопределение из BDecorator никогда не вызывается?
Он вызывается:
Из BDecorator
класса добавьте следующее Statement
:
@Override
protected void foo(String message) {
System.out.println("Do I even exist?");
this.decoratedB.foo("Testing a foo decorator: " message);
}
вывод:
Do I even exist?
Testing a foo decorator: Hello world!
Do I even exist?
Testing a foo decorator: Hello world!
Testing a bar decorator: Goodbye world!
Testing a bar decorator: Goodbye world!
Вызывается метод foo из BDecorator
класса, а затем перенаправляет вызов foo
method
из B, переданный конструктору BDecorator
в вашем случае:
new BDecorator(new B(...));
и объект экземпляра из класса B
.