2

Let assume that we develop a simple blog website backend and the app have three or more POJO classes like Post, User, Category.

All class have the same fields such as id, createdDate, updateDate.

As java-programmers, we apply Encapsulation to all the fields in a class using private access modifier. My question is very simple: Can we perform encapsulation using default access modifier with Inheritance?

The code:

public abstract class BaseModel {
    String id;
    LocalDateTime createdDate;
    LocalDateTime updatedDate;
    // getters and setters
}

public class Post extends BaseModel{
    private String slug;
    private String name;
    private String title;
    // other fields, getters and setters
}

public class Category extends BaseModel{
    private String name;
    private String slug;
    // other fields, getters and setters
}
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
swim
  • 119
  • 1
  • 9
  • The code compiles, you can never assign a Post to a Category or vice versa, so the fields with the same names are completely isolated. What is the real question? And what are those Annotations? If they are not related to your problem, you should remove them for your question here, if they are related, please describe how. Also I want to add that "encapsulation" means that you can access data (fields) only via the methods of a class, but I don't see methods here. Confuses me a bit. – cyberbrain Mar 27 '22 at 14:57
  • methods that accessed fields is getter and setters :) and all annotation is cleared in code blocks. I didn't understand that never assign a Post a Category and why? – swim Mar 27 '22 at 15:17
  • You cannot have a `Post myPost = new Post();` and then a `Category myCategory = myPost;`. (Or vice versa.) Will not compile. You could do a `BaseModel myBase = myPost;` but you cannot access any of the fields of `myPost` with an implemenation of `BaseModel` - you could have a methode declared in `BaseModel` thats overridden in `Post` and accesses the fields from `Post` there. – cyberbrain Mar 27 '22 at 15:24

2 Answers2

2

Protected modifier

The common practice it to use protected access modifier to encapsulate class members within the Parent class.

Package private fields and methods will not be visible to subclasses located outside the package of the Parent class. Conversely, protected variables and behavior will be accessible to any subclass regardless of its location.

Composition vs Inheritance

Inheritance is not always beneficial, in-fact there are many cases where it isn't. You need to consider all pros and cons before making class-design decisions like whether a particular class will derive from another class.

What are the benefits of extending the BaseModel?

It doesn't feel like you can take advantage from the polymorphism here. Because the only behavior you can use with the parent type BaseModel are getters and setters for dates of creation and update. And at the same time you'll not be able to access the specific behavior of subclasses.

It looks rather as a drawback because BaseModel isn't designed for extension. I.e. it neither contains any useful implementations (I'm not taking getters/setters into account), no abstract methods are meant to be implemented by its subclasses (that would be a scenario of advantageous polymorphism).

In fact, you are extending BaseModel just in order to reuse a couple of variables. That not a compelling reason to utilize inheritance.

Your example is a perfect case to substitute an IS A relationship (Post is a BaseModel) with HAS A relationship (Post includes BaseModel).

The design technic, when a class contains its instance field an instance of another class instead of extending this class, is called Composition.

As a general rule, composition is a more preferable approach than inheritance. As well as inheritance, it allows to reuse the behavior and at the same time it classes closely coupled.

If you make the BaseModel a concrete class and apply composition to other classes, your code will look like that.

public class BaseModel {
    private String id;
    private LocalDateTime createdDate;
    private LocalDateTime updatedDate;
    // getters and setters
}

public class Post {
    private BaseModel base;
    private String slug;
    private String name;
    private String title;
    // other fields, getters and setters
}

public class Category {
    private BaseModel base;
    private String name;
    private String slug;
    // other fields, getters and setters
}
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
  • “Package private fields and methods will be visible only to subclasses located in the same package…” That is not correct. Package-private members are visible to *all* classes in the same package. – VGR Mar 27 '22 at 22:34
  • @VGR Sure. I was trying to convey these fields and behavior of the *parent* will **not be accessible** to *subclasses* in other packages. I was focusing only on child-parent relationships, and didn't mean that other classes from the same package will not see them. I'll rephrase this sentence to avoid confusion. – Alexander Ivanchenko Mar 27 '22 at 23:16
  • Actually this question is enough for me: "What is the benefits of `BaseModel`?" I want to prevent repetitive expressions/statements. I know that this way a little bit against the OOP principles. As you know this classes are used at ORM, so approach of `Post has a BaseModel` may not give correct results. – swim Mar 28 '22 at 04:36
  • Although repetitive expressions/statements, I should separate all class objects. – swim Mar 28 '22 at 04:44
  • @swim `this classes are used at ORM` - If you're working with a code base that already exists and your entity classes inherit from `BaseModel`, then it's reasonable to stick with that structure. In this case, you might make a couple of enhancements that will not affect the underlying database to make the usage of `BaseModel` as a super-type beneficial. But if you're building your own project, and you're free to make changes in it, I suggest you to make the `BaseModel` to be an [**embeddable object**](https://www.baeldung.com/jpa-embedded-embeddable). – Alexander Ivanchenko Mar 28 '22 at 09:28
  • Ok :D Very Well. can this structure cause a problem when transaction process? Actually, this is very basic idea but i couldn't see use anybody it. This is make me think! – swim Mar 28 '22 at 12:08
  • @swim *can this structure cause a problem when transaction process?* - I don't think then it could break the things. It's not a brand-new feature. `@Embeddable` is a part of JPA from the very beginning. Embedded objects are parts of entities, they don't have their own persistent identity (in the DB an embeddable object is represented with a set of columns in a table corresponding to its entity-class). When you are changing the entity somehow, after closing the session, all changes get reflected in the DB. – Alexander Ivanchenko Mar 29 '22 at 06:18
  • @swim Take a look at this [tutorial](https://docs.oracle.com/javaee/7/tutorial/persistence-intro001.htm#BNBQA) – Alexander Ivanchenko Mar 29 '22 at 06:18
0

the default modifier signifies it's only accessible in the package. So if you are using a child class in a different package, the fields will not be accessible.

If that's want you want, great! It's encapsulated.

If that's not what you want, bummer... BUT you still have the protected modifier.

This let's a child class inherit the fields even if it's in a different package.

See this answer too: What is the difference between public, protected, package-private and private in Java?