Selenium automates browser and to achieve this, Selenium has provided many classes and interfaces.
Let’s start with some basic concepts of java:
- We can not create an object of interface, i.e. we can not instantiate an interface.
- Interface has abstract methods means they do not have body, only declaration.
- We can pass reference of any superclass or super interface to its sub class object which is called Upcast.
- When we upcast a subclass object, we restrict that object from using sub class methods. To use subclass methods, we must downcast the object to subclass object.
- When we up cast a subclass object say SubObj and try to access a method say SuperClassMethod of superclass by that object, and that method is overridden in subclass, then method of subclass will be called without down casting subclass object. It is called runtime polymorphism. It is major concept on which selenium works.
Let’s understand above diagram in details:
- SearchContext is a top most interface which has only two methods names findElement() and findElements(). These methods will be abstract as SearchContext is an interface.
- WebDriver is also an interface which extends SearchContext. WebDriver has many abstarct methods like get(String url), close(), quit() , getWindowHandle etc. WebDriver has nested interfaces names Window, Navigation, Timeouts etc. These nested interfaces are used to perform/group specific operation like getPosition(), back(), forward() etc.
- Then we have browser specific driver classes like ChromeDriver(), EdgeDriver(), FirefoxDriver() etc.
Q 1: Why do we upcast any browser driver class object to WebDriver?
Why do we not upcast to SearchContext or RemoteWebDriver?
A: In selenium, maximum time when we create an object of any browser driver class, we do upcast.
E.g. WebDriver driver= new FirefoxDriver();
Reasons are as below:
- It helps in launching any browser type using same instance of WebDriver. WebDriver is super interface for all browser classes like FirefoxDriver , ChromeDriver etc. So WebDriver instance can hold object of any browser class.
WebDriver driver= new FirefoxDriver();
WebDriver driver= new ChromeDriver();
It will be helpful if you want to perform cross browser testing.
2. It is a good programming practice to upcast the object to a level where you can be a in position to use maximum Types(Classes, Interface are called Type) down the hierarchy without much downcast and you should not lose important members of Types up in the hierarchy. If you are on Top of hierarchy, you can navigate anywhere down to hierarchy. Upcasted object can be downcasted.
So here we have tree options. Upcast to RemoteWebDriver or WebDriver or SearchContext. If we upcast browser class object to SearchContext, it will not be so good as it has only two methods and to use other types below in hierarchy, we need to do down cast.
If we upcast to WebDriver, we can use many useful methods of WebDriver without any explicit downcast. Upcast to WebDriver if you want to run scripts locally. Upcast to RemoteWebDriver, if want to run on remote machine.
Remember, there is no such mandatory rule that you need to upcast or downcast. It is just way of proper programming.
i.e. no need to do downcasting in below case:
FirefoxDriver driver2= new FirefoxDriver();
But, if we write as below:
WebDriver driver= new FirefoxDriver();
- WebElement is an interface which extends SearchContext and TakesScreenshot interfaces. It has many useful abstract methods like click(), sendKeys(), isSelected() etc.
- RemoteWebElement is a fully implemented class of WebElement interface. In fact, findElement() and findElements() of SearchContext interface have been defined properly in this class only.
- When we search for some element using findElement or findElements() method, a type of RemoteWebElement class is up casted to WebElement. And when we perform any action on webelement like click(), method defined in RemoteWebElement class will be executed because of overriding concept.
I hope, This post will be very useful as it clears why we do upcast and downcast while creating script. Now you must be able to answer.