Обновлено: похоже, что моя проблема исходит совершенно из другого места. Если вы еще не прочитали остальную часть этой темы, у меня есть class A, class B расширение class A и class BDecorator расширение 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
Поскольку поток относится к 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);
}
}
Короче говоря, я пытаюсь переопределить метод от родителя, который уже реализовал указанный метод от своего родителя (метод переопределения внука от родителя, метод реализации от прародителя).
Вторая итерация декоратора: переопределение новой функции панели, созданной в 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 из BDecorator?




Возникает вопрос: почему переопределение
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, а затем перенаправляет вызов в foomethod из B, переданный конструктору BDecorator в вашем случае:
new BDecorator(new B(...));
и экземпляр объекта из класса B.