Search code examples
javaaccess-modifiers

Is it best practice to use a protected object in a parent class, or have it private with a protected/public getter?


using a small example which has a hierarchy of:

  • BaseModel
  • OrderModel extends BaseModel

Inside the BaseModel i want to have an object Faker in any class which extends it, what is the correct approach here?

private Faker faker = new Faker();

protected Faker getFaker() {
    return this.faker;
}

protected Faker faker = new Faker();

I have opted for this:

public class Order extends BaseModel {
    private static final Logger LOG = LogManager.getLogger(Order.class);

    private String orderName;
    private String orderAddress;
    private String orderEmail;
    private String orderPaymentType;

    public Order(String order_paymentType) {
        this.orderName = getFaker().name().fullName();
        this.orderAddress = getFaker().address().streetAddress();
        this.orderEmail = getFaker().internet().emailAddress();
        this.orderPaymentType = order_paymentType;
        LOG.info("Instantiating order: " + this.toString());
    }

    public String getOrderName() {
        return this.orderName;
    }

    public String getOrderAddress() {
        return this.orderAddress;
    }

    public String getOrderEmail() {
        return this.orderEmail;
    }

    public String getOrderPaymentType() {
        return this.orderPaymentType;
    }

    @Override
    public String toString() {
        return "Order [orderName=" + orderName + ", orderAddress="
                + orderAddress + ", orderEmail=" + orderEmail
                + ", orderPaymentType=" + orderPaymentType + "]";
    }

}

I opted for this and to be honest, I don't entirely know why, what is the correct way to handle this situation and more importantly why?

Faker is an object used to generate fake information basically.


Solution

  • The limitation in you design is that Faker will always be present in all models and that is a hard dependancy you should avoid. By now, the current Java best practice is to favour composition over inheritance.

    So we can have an interface called DataProvider

    interface DataProvider {
      String address();
       ....
    }
    

    And Fake would implement this address

    class FakeDataProvider implements DataProvider...\ and now you can inject a DataProvider

    public Order(String order_paymentType, DataProvider dataProvider){
      this.orderName = dataProvider.name().fullName();
      ....
    }
    

    And now you replace Faker with something else without touching Order code. So my answer is: don't use inheritance all together.