Java 模型中的封装 Class

Encapsulation in the Java Model Class

假设我们开发了一个简单的博客网站后端,并且该应用程序具有三个或更多 POJO classes,例如 PostUser, Category.

所有 class 具有相同的字段,例如 idcreatedDateupdateDate

作为 java 程序员,我们使用 private 访问修饰符将 封装 应用于 class 中的所有字段。我的问题很简单:我们可以使用默认访问修饰符继承执行封装吗?

代码:

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
}

默认修饰符表示它只能在包中访问。因此,如果您在不同的包中使用 child class,将无法访问这些字段。

如果这是您想要的,太好了!封装好了。

如果这不是你想要的,那就太可惜了......但你仍然拥有受保护的修饰符。

这让我们 child class 继承字段,即使它在不同的包中。

也看到这个答案:What is the difference between public, protected, package-private and private in Java?

受保护的修饰符

通常的做法是使用 protected 访问修饰符来 封装 class [=] 中的成员48=]Parent class.

Package private 字段和方法对 subclasses 不可见 Parentclass。相反,任何 subclass 都可以访问 protected 变量和行为,无论其位置如何。

组合与继承

继承并不总是有益的,in-fact在很多情况下并非如此。在做出 class-design 决定之前,您需要考虑所有利弊,例如特定 class 是否会派生自另一个 class.

扩展BaseModel好处是什么?

这里的 多态性 似乎无法利用。因为您可以使用 parent 类型 BaseModel 的唯一行为是创建和更新日期的 getter 和 setter。同时您将无法访问 subclasses.

的特定行为

它看起来更像是一个缺点,因为 BaseModel 不是为扩展设计的 。 IE。它既不包含任何有用的实现(我没有考虑 getters/setters),它的子classes(即将是一个有利的 多态性 ) 的场景。

事实上,您扩展 BaseModel 只是为了重用几个变量。这不是利用 继承 .

的令人信服的理由

你的例子是用 HAS A[ 替换 IS A 关系(PostBaseModel)的完美案例=69=]关系(Post包括BaseModel)。

设计技术,当一个 class 包含其实例字段另一个 class 的实例而不是扩展此 class 时,称为 Composition.

一般来说,组合是比继承更可取的方法。除了继承之外,它还允许重用行为,同时 class 紧密耦合。

如果您使 BaseModel 成为具体的 class 并将 组合 应用于其他 class,您的代码将看起来像那样。

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
}