封装是面向对象编程(OOP)中的基本概念之一。它描述了将数据和处理该数据的方法捆绑在一个单元中的想法,例如,Java中的一个类。
这个概念也经常用于从外部隐藏对象的内部表示或状态。这称为信息隐藏。这种机制的总体思路很简单。如果您有一个从对象外部看不到的属性,并将其与提供读取或写入访问权限的方法捆绑在一起,那么您可以隐藏特定信息并控制对对象内部状态的访问。
如果您熟悉任何面向对象的编程语言,您可能知道这些方法是 getter 和 setter 方法。顾名思义,getter 方法检索属性,setter 方法更改它。根据您实现的方法,您可以决定一个属性是否可以读取和更改,或者它是只读的,还是根本不可见。正如稍后将向您展示的,您还可以使用 setter 方法来实现额外的验证规则,以确保您的对象始终具有有效状态。
Java中的封装
这是一个如此基本的概念,以至于大多数 Java 开发人员在使用它时都没有考虑过。这只是您设计Java类的方式。您将一组存储对象当前状态的属性与使用这些属性的一组方法捆绑在一起。
该CoffeeMachine例子
例如,当创建CoffeeMachine类时,就是这样做的。属性configMap、beans、grinder和brewingUnit存储CoffeeMachine对象的当前状态。方法brewCoffee、brewEspresso、brewFilterCoffee和addBeans对这些属性实现了一组操作。
Java中的信息隐藏
正如开头所解释的,您可以使用封装概念来实现信息隐藏机制。与抽象概念类似,这是Java中最常用的机制之一。您可以在几乎所有实现良好的Java类中找到它的示例。
您可以通过使您的类属性无法从外部访问并为其他类可读或可更新的属性提供 getter 和/或 setter 方法来实现这种信息隐藏机制。
访问修饰符
Java支持四种访问修饰符,您可以使用它们来定义类、方法和属性的可见性。它们中的每一个都指定了不同级别的可访问性,并且每个类、方法或属性只能使用一个修饰符。根据经验,您应该始终使用仍然允许您实现业务逻辑的最严格的修饰符。
这些修饰符从限制最多到最少:
私人的
没有修饰符
受保护
公开的
让我们仔细看看这些修饰符中的每一个,并讨论何时应该使用它们。
私人
这是最严格和最常用的访问修饰符。如果将private修饰符与属性或方法一起使用,则只能在同一类中访问它。相同或不同包中的子类或任何其他类无法访问此属性或方法。
根据经验,private修饰符应该是所有不应从外部类调用的属性和内部方法的默认选择。当您使用继承时,您可能需要对该规则进行例外处理,并且某些子类需要直接访问属性或内部方法。在这种情况下,您应该使用protected修饰符而不是private。
无修饰符
当您没有为您的属性或方法提供任何访问修饰符时,您可以在您的类中以及从同一包中的所有类访问它。这就是为什么它通常被称为包私有的。
在CoffeeMachine示例中,我使用private修饰符来限制对所有属性以及brewEspresso和brewFilterCoffee方法的访问。这些属性和方法只能在CoffeeMachine类中使用,而不是公共 API 的一部分。
一开始这可能看起来有点令人困惑,但是当包中的类实现一组明确定义的逻辑并且您想要控制可用于该包外的类的 API 时,这非常有用。然后,您可以使用包可见性来实现只能由该包中的类使用的方法。这允许您创建包内部和外部 API。
受保护
具有访问修饰符protected 的属性和方法可以在您的类中、同一包中的所有类以及相同或其他包中的所有子类中访问。
该保护的修饰符被主要用于内部方法需要被调用或者由子类覆盖。您还可以使用它来允许子类直接访问超类的内部属性。
民众
这是限制最少的访问修饰符。使用public修饰符的方法和属性可以在当前类和所有其他类中访问。
公共方法和属性成为您的类和包含它们的任何组件的公共 API 的一部分。对于任何属性来说,这几乎从来都不是一个好主意,在对方法使用此修饰符之前,您应该三思而后行。
如果一个方法是公开可用的,您需要确保它有据可查,并且它可以稳健地处理任何输入值。还要记住,这个方法迟早会被你的应用程序的某些部分使用,这将使更改或删除它变得困难。
通常,您的公共 API 应尽可能精简,并且仅包含旨在由应用程序的其他部分或外部客户端使用的方法。
CoffeeMachine类、它的构造函数以及brewCoffee和addBeans方法就是这种情况。该CoffeeMachine类有因为它代表了咖啡机的接口是公开的。它旨在供不必属于同一包的其他类使用。构造函数和对brewCoffee和addBeans方法可以被其他类调用创建的新实例CoffeeMachine并通过添加咖啡豆或冲泡的咖啡一杯新鲜与它进行交互。
该brewCoffee方法给出了不同的访问修饰符的另一个好处。您不仅可以使用它来隐藏信息,还可以使用它来支持抽象。公共brewCoffee方法抽象了brewFilterCoffee和brewEspresso方法的内部细节,这两个方法都是私有的。访问修饰符确保外部类只能调用brewCoffee方法提供的抽象,而不能调用内部方法。
概括
封装是面向对象编程的核心概念之一。它描述了将数据和对这些数据进行操作的方法捆绑到一个单元中。
它通常用于实现信息隐藏机制。这种机制降低了属性对当前类的可访问性,并使用公共 getter 和 setter 方法来控制和限制对这些属性的外部访问。这些方法不仅允许您定义可以读取或更新的属性,而且还允许您在更改属性之前验证新值。
封装提供了隐藏数据的基本属性,从而为用户数据提供了安全性。执行封装是一种很好的 OOP 实践,但它仍然需要与强大的 APM 解决方案(如Retrace)搭配使用以进行错误监控。