封裝 (物件導向程式設計)

在物件導向程式設計方法中，封裝（）是指，一種將抽象性函式介面的實作細節部份包裝、隱藏起來的方法。同時，它也是一種防止外界呼叫端，去存取物件內部實作細節的手段，這個手段是由程式語言本身來提供的。封裝被視為是物件導向的四項原則之一。

適當的封裝，可以將物件使用介面的程式實作部份隱藏起來，不讓使用者看到，同時確保使用者無法任意更改物件內部的重要資料，若想接触資料只能通过公开接入方法（Publicly accessible methods）的方式（ 如："getters" 和"setters"）。它可以讓程式碼更容易理解與維護，

解释 
在面向对象的语言里，封装往往指以下两个相关联但是独立的概念，有时候这两者是存在因果关系。

 一种编程语言的机制，限制直接访问某些对象的部件。
 一种编程语言的结构体，其将数据和操作该数据的方法绑在一起，提供了便利性。

一些编程语言的研究者和学者将定义①或者定义①+②作为辨认一门语言是否为面向对象语言的标准之一。一些编程语言提供了闭包作为封装，但是这种功能不属于面向对象的范畴。

在许多编程语言里，组件并不会自动隐藏并且能够被重写，因此，一些倾向于定义②的人会将信息隐藏（information hiding）作为一个单独的定义③列举出来。

在使用类的大多面向对象的编程语言中，虽然封装是被支持的，但是仍有其他替代品可以选择。

封装和继承 
《Design Patterns》的作者们曾经大篇幅地讨论封装和继承的矛盾。根据他们自身的经验，设计师们滥用继承。他们认为继承将破坏封装，考虑父类的实现细节将暴露给子类。

父类的内部实现对于子类来说是不透明的（实现一个子类时， 你需要了解父类的实现细节， 以此决定是否需要重写某个方法）。同时，一旦父类被修改，因为子类依赖着父类，所以子类的实现也需要被重新审视。

信息隐藏 
封装可以隐藏成员变量以及成员函数，对象的内部实现通常被隐藏，并用定义代替。举个例子，仅仅对象自身的方法能够直接接触或者操作这些成员变量。隐藏对象内部信息能供保证一致性：当用户擅自修改内部部件的数据，这可能造成内部状态不一致或者不可用；隐藏对象内部信息能阻止这种后果。一个众所周知的好处是，降低系统的复杂度和提高健壮性。

大多数语言（如：C++、C#、 Delphi、Java）通过设定等级去控制内部信息隐藏，经典的是通过保留字 public 暴露信息和 private隐藏信息。一些语言（如： Smalltalk 和 Ruby ）只允许对象去访问隐藏信息。

通常，也是存在方法去暴露隐藏信息，如通过反射(Ruby、Java、C#、etc.)或名字修饰(Python)。

程式範例

保留字

C#範例
这是一段C#代码，演示了如何使用private关键字限制变量的访问：
namespace Encapsulation 
{
	class Program 
	{
		public class Account 
		{
			private decimal accountBalance = 500.00m;

			public decimal CheckBalance() 
			{
				return accountBalance;
			}
		}

		static void Main() 
		{
			Account myAccount = new Account();
			decimal myBalance = myAccount.CheckBalance();

			/* Main方法能够通过public的“CheckBalance”方法确认账户余额，但是不能更改它 */
		}
	}
}

JAVA範例
下面是Java的演示程序:
public class Employee {
    private BigDecimal salary = new BigDecimal(50000.00);
    
    public BigDecimal getSalary() {
        return salary;
    }

    public static void main() {
        Employee e = new Employee();
        BigDecimal sal = e.getSalary();
    }
}

名字修饰（Name mangling） 
下面是Python的要给实例，Python并不支持隐藏变量。然而约定俗成，_var 形式的变量被认为是私有变量。class Car: 
    def __init__(self):
        self._maxspeed = 200
 
    def drive(self):
        print(f'maximum speed is {self._maxspeed}')
 
redcar = Car()
redcar.drive()  # 打印 'maximum speed is 200'

redcar._maxspeed = 10
redcar.drive()  # 打印 'maximum speed is 10'

参考文献 

面向对象的程序设计