JavascriptExecutor — это интерфейс, который предоставляет некоторый код по умолчанию для метода executeScript.
RemoteWebDriver реализует этот интерфейс и переопределяет метод следующим образом:
@Override
public Object executeScript(String script, Object... args) {...}
Когда мы создаем экземпляр WebDriver, мы используем такой экземпляр, как FireFoxDriver или ChromeDriver. Эти методы наследуют родительский метод executeScript.
Тем не менее, всякий раз, когда мы хотим вызвать executeScript, мы никогда не вызываем этот метод непосредственно из объекта драйвера, например:
driver.executeScript(...)
Вместо этого мы всегда сначала приводим его к интерфейсу, а затем вызываем.
Вот пример кода:
WebDriver driver = new FirefoxDriver();
JavascriptExecutor executor =(JavascriptExecutor)driver;
executor.executeScript("window.location.href = 'https://google.com';");
Зачем нам нужно приводить драйвер к JavascriptExecutor? Почему мы не можем просто вызвать driver.executeScript вместо этого? В качестве альтернативы, мы могли бы вместо этого преобразовать его в RemoteWebDriver?
@chrylis-cautiouslyoptimistic- Реализация выполняется классом RemoteWebDriver. Но это по-прежнему не меняет того факта, что мы приводим драйвер ChromeDriver/FireFox к родительскому типу.
Смотрите мой комментарий здесь: stackoverflow.com/questions/70397713/…
в основном тип (интерфейс - это в основном тип) веб-драйвера не гарантирует метод javascriptexecutor... некоторые драйверы могут фактически не реализовывать его. (хотя я не могу придумать ни одного, который не... может быть, драйверы appium или winium?)
@pcalkins Не должно иметь значения, реализует ли его дочерний класс или нет (например, appium). Этот интерфейс уже реализован родительским RemoteWebDriver, что означает, что этот метод виден дочернему экземпляру. Я не вижу причин, по которым мы постоянно приводим типы перед вызовом метода интерфейса.
да, это может быть скорее устаревшая вещь ... но, поскольку вы уже выполнили приведение к WebDriver, неизвестно, будет ли оно доступно, пока вы не приведете тип. Если вы используете только один драйвер в своем коде, вы можете с самого начала просто привести его к FirefoxDriver. (на самом деле вы бы не выполняли кастинг в этот момент, просто сохраняя тип как FirefoxDriver...) Архитектура, вероятно, изменится по мере того, как все больше драйверов будут соответствовать стандарту W3C.
@pcalkins Ваш ответ правильный. Не могли бы вы поставить это как ответ на этот вопрос? Я думаю, что это ответ. Спасибо!




Мы приводим типы, потому что наш код обычно использует тип webdriver, который является интерфейсом и не включает метод executeScript.
Когда вы передаете драйвер как тип "webdriver", классы предполагают, что он имеет только методы интерфейса WebDriver. Вы также можете привести его к типу Chromedriver, но тот же код не будет работать для Geckodriver или других типов.
Кредиты pcalkins для этого ответа.
Следовательно, вы передаете его интерфейсу JavascriptExecutor, чтобы код оставался универсальным, чтобы он работал с Geckodriver/Chromedriver и т. д. В качестве альтернативы вы также можете привести его к RemoteWebDriver, и он все равно будет работать. Но это более читабельно, если привести к JavascriptExecutor.
Вот диаграмма архитектуры, которая прекрасно это объясняет. Кредиты qacult.com для этого изображения.
Что вы подразумеваете под "родительскими методами"?
WebDriverне продлеваетсяJavaScriptExecutor. И что вы подразумеваете под «не определено в этом интерфейсе»? Это прямо здесь.