Передача в родительский элемент информации о том кто вызвал метод родительского класса
Вопрос заключается в том, что у меня есть классы, которые описывают веб-элементы (Button, Input и т.д).
Я решил создать базовый класс, от которого они все наследуются (BaseElement) и вынести в него все методы, которые можно сделать над всеми элементами (click, move и прочее), но из-за того, что я везде использую return this, чтобы просто через точку вызывать методы, когда я вызываю сначала метод родителя, мне перестают быть доступны методы потомка.
Есть возможность из родителя возвращать ссылку на объект, который и вызвал метод родителя?
Пример метода родителя:
public BaseElement clickElement() {
Allure.step("Клик на " + typeElement + " " + getName() + "'");
WaitT.elementToBeClickable(this.getWrappedElement());
this.getWrappedElement().click();
return this;
}
Пример метода потомка:
public CheckBox enableCheckBox() {
if (!isChecked()){
Allure.step("Клик по чек-боксу '" + getName() + "'");
WaitT.elementToBeClickable(this.getWrappedElement());
this.getWrappedElement().click();
}
return this;
}
Пример использования, тут ошибка, потому что метод родителя вернул BaseElement, а не TextBox:
var loginPage = new LoginPage();
loginPage.loginUser.clickElement().enterTextFromTextBox(LOGIN);
Ответы (2 шт):
Если метод класса возвращает this, то это не значит, что он фактически возвращает объект ровно от данного класса.
Класс ведь может быть и абстрактным, а от абстрактного класса объекты не могут быть созданы вообще. Что в таком случае означает возврат this? Он означает возврат объекта от того класса, для которого этот метод родителя был вызван.
Да, возвращаемый тип у метода - родительский. Но в месте вызова метода мы ведь точно знаем класс, объект от которого вызывает этот метод. Соответственно, можем не боясь ошибок использовать приведение типов, что и будет продемонстрировано ниже.
Родительский класс:
public abstract class SuperClass {
public SuperClass superClassMethod() {
System.out.println("SuperClass hello!");
return this;
}
}
Подкласс:
public class FirstSubClass extends SuperClass {
public FirstSubClass firstSubClassMethod() {
System.out.println("FirstSubClass hello!");
return this;
}
}
Как делается приведение типов в этом случае:
public class Main {
public static void main(String[] args) {
FirstSubClass first = new FirstSubClass();
((FirstSubClass) first.superClassMethod()).firstSubClassMethod();
// привели к FirstSubClass, ведь точно знаем, что родительский метод вернёт объект именно от него
}
}
Результат:
SuperClass hello!
FirstSubClass hello!
В классах наследниках можно переопределить необходимые методы, указав при этом класс наследника как возвращаемый тип
class BaseElement {
public BaseElement clickElement() {
return this;
}
}
class CheckBox extends BaseElement {
@Override
public CheckBox clickElement() {
super.clickElement();
return this;
// либо так
// return (CheckBox) super.clickElement();
}
public CheckBox enableCheckBox() {
return this;
}
}
new CheckBox().clickElement().enableCheckBox();
new BaseElement().clickElement()
// .enableCheckBox() - compile error