You don't have to return an instance of that class, but in many cases it's quite useful.
As @Grasshopper wrote in the comments, it's useful to already create an instance of the class that corresponds to a new page that you're opening. For example, you have a Login page that contains the following:
1) username field
2) password field
3) login button
The methods for entering the username and the password are as following:
public class LoginPage extends BasePage {
public LoginPage (WebDriver driver) {
super(driver);
}
public LoginPage enterUsername(String username) {
WebElement usernameField = driver.findElementBy...;
usernameField.sendKeys(username);
return this; // returns this instance because it stays on the LoginPage
}
public LoginPage enterPassword (String password) {
WebElement passwordField = driver.findElementBy...;
passwordField.sendKeys(password);
return this; // returns this instance because it stays on the LoginPage
}
}
Then you have a method that clicks on the login button, which redirects you to, let's say, homepage.
public HomePage clickLoginButton () {
WebElement loginButton = driver.findElementBy...;
loginButton.click();
return new HomePage(driver); // returns a new instance on the HomePage because homepage will be opened
}
The cool thing about returning 'this' instance and returning a new instance, is that in your test class, you can use your methods one after another, without having messy looking code:
LoginPage loginPage = new LoginPage(driver);
loginPage.enterUsername("username")
.enterPassword("password");
HomePage homepage = loginPage.clickLoginButton();