Until now we described just Webelements on pages. But maybe you want to add some more value to your PageObjectes and add higher-value-methods than just locator-methods

@Page(name="Login")
public abstract class LoginPO {
  @PageAccessor(uri="login.html")
  public abstract void open();

  public void doLogin(String username, String password) {
    usernameTextbox().type(username);
    passwordTextbox().type(password);
    submitLoginButton().click();
  }

  @Locator(name="Username", xpath="//input[@name='username']")
  public abstract ITextBox usernameTextbox();

  @Locator(name="Password", xpath="//input[@name='password']")
  public abstract ITextBox passwordTextbox();

  @Locator(name="Login Submit", cssSelector=".submitLoginButton")
  public abstract IButton submitLoginButton();
}

In this example we created a PageObject as an abstract class not as an interface. Now it's possible to add some higher value methods to that PageObject.

Replace locator-methods by valuable methods

If you don't want to expose any "low level" locator methods to your tests but only "higher value" methods you can use the an abstract class and make your locators package-private.

@Page(name="Login")
public abstract class LoginPO {
  @PageAccessor(uri="login.html")
  public abstract void open();

  public void doLogin(String username, String password) {
    usernameTextbox().type(username);
    passwordTextbox().type(password);
    submitLoginButton().click();
  }

  @Locator(name="Username", xpath="//input[@name='username']")
  abstract ITextBox usernameTextbox();

  @Locator(name="Password", xpath="//input[@name='password']")
  abstract ITextBox passwordTextbox();

  @Locator(name="Login Submit", cssSelector=".submitLoginButton")
  abstract IButton submitLoginButton();
}

Locator-methods are now package-private, so only valuable methods are visible in your tests

Separate Locators from POs

To separate low level methods and valuable methods you can separate them in two classes and use inheritance.

@Page(name="Login")
public abstract class LoginPO implements LoginLocator {
  public void doLogin(String username, String password) {
    usernameTextbox().type(username);
    passwordTextbox().type(password);
    submitLoginButton().click();
  }
}

public interface LoginLocator {
  @PageAccessor(uri="login.html")
  void open();

  @Locator(name="Username", xpath="//input[@name='username']")
  ITextBox usernameTextbox();

  @Locator(name="Password", xpath="//input[@name='password']")
  ITextBox passwordTextbox();

  @Locator(name="Login Submit", cssSelector=".submitLoginButton")
  IButton submitLoginButton();
}

If you write your locator-methods into an interface they will be allways public. If you don't want that, the following pattern might be interesting for you.

Separate Locators from POs and make Locators not visible

Writing your locators into an abstract class instead an interface allows you to make them package-private.

@Page(name="Login")
public abstract class LoginPO implements LoginLocator {
  public void doLogin(String username, String password) {
    usernameTextbox().type(username);
    passwordTextbox().type(password);
    submitLoginButton().click();
  }
}

public abstract class LoginLocator {
  @PageAccessor(uri="login.html")
  public abstract void open();

  @Locator(name="Username", xpath="//input[@name='username']")
  abstract ITextBox usernameTextbox();

  @Locator(name="Password", xpath="//input[@name='password']")
  abstract ITextBox passwordTextbox();

  @Locator(name="Login Submit", cssSelector=".submitLoginButton")
  abstract IButton submitLoginButton();
}