封裝,一種將抽象性函式介面的實作細節部份包裝、隱藏起來的方法
在物件導向程式設計 方法中,封裝 (英語:Encapsulation )是指,一種將抽象 性函式介面的實作細節部份包裝、隱藏起來的方法。同時,它也是一種防止外界呼叫端,去存取物件 內部實作細節的手段,這個手段是由程式語言本身來提供的。封裝被視為是物件導向 的四項原則之一。
適當的封裝,可以將物件使用介面的程式實作部份隱藏起來,不讓使用者看到,同時確保使用者無法任意更改物件內部的重要資料,若想接触資料只能通过公开接入方法(Publicly accessible methods) 的方式( 如:"getters" 和"setters")。它可以讓程式碼更容易理解與維護,也加強了程式碼的安全性。 [來源請求]
解释
在面向对象的语言里,封装往往指以下两个相关联但是独立的概念,有时候这两者是存在因果关系。[ 1] [ 2]
一种编程语言的机制,限制直接访问某些对象的部件。[ 3] [ 4]
一种编程语言的结构体,其将数据和操作该数据的方法 绑在一起,提供了便利性。[ 5] [ 6]
一些编程语言的研究者和学者将定义①或者定义①+②作为辨认一门语言是否为面向对象语言的标准之一。一些编程语言提供了闭包 作为封装,但是这种功能不属于面向对象的范畴。
在许多编程语言里,组件并不会自动隐藏并且能够被重写,因此,一些倾向于定义②的人会将信息隐藏 (information hiding)作为一个单独的定义③列举出来。
在使用类的大多面向对象的编程语言中,虽然封装是被支持的,但是仍有其他替代品可以选择。
《Design Patterns》的作者们曾经大篇幅地讨论封装和继承的矛盾。根据他们自身的经验,设计师们滥用继承。他们认为继承将破坏封装,考虑父类的实现细节将暴露给子类。[ 7]
父类的内部实现对于子类来说是不透明的(实现一个子类时, 你需要了解父类的实现细节, 以此决定是否需要重写某个方法)。[ 8] 同时,一旦父类被修改,因为子类依赖着父类,所以子类的实现也需要被重新审视。
信息隐藏
封装可以隐藏成员变量以及成员函数,对象的内部实现通常被隐藏,并用定义代替。举个例子,仅仅对象自身的方法能够直接接触或者操作这些成员变量。隐藏对象内部信息能供保证一致性:当用户擅自修改内部部件的数据,这可能造成内部状态不一致或者不可用;隐藏对象内部信息能阻止这种后果。一个众所周知的好处是,降低系统的复杂度和提高健壮性 。
大多数语言(如: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.00 m ;
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 ();
}
}
下面是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'
参考文献
^ Scott, Michael Lee. Programming language pragmatics 2. Morgan Kaufmann. 2006: 481 . ISBN 978-0-12-633951-2 . Encapsulation mechanisms enable the programmer to group data and the subroutines that operate on them together in one place, and to hide irrelevant details from the users of an abstraction.
^ Dale, Nell B.; Weems, Chip. Programming and problem solving with Java 2nd. Jones & Bartlett. 2007: 396 . ISBN 978-0-7637-3402-2 .
^ Mitchell, John C. Concepts in programming languages . Cambridge University Press. 2003: 522 . ISBN 978-0-521-78098-8 .
^ Pierce, Benjamin . Types and Programming Languages . MIT Press. 2002: 266 . ISBN 978-0-262-16209-8 .
^ Rogers, Wm. Paul. Encapsulation is not information hiding . JavaWorld. 18 May 2001 [2019-11-22 ] . (原始内容 存档于2013-10-29).
^ Connolly, Thomas M.; Begg, Carolyn E. Ch. 25: Introduction to Object DMBS § Object-oriented concepts. Database systems: a practical approach to design, implementation, and management 4th. Pearson Education. 2005: 814 . ISBN 978-0-321-21025-8 .
^ Gamma, Erich; Helm, Richard; Johnson, Ralph; Vlissides, John. Design Patterns . Addison-Wesley. 1994. ISBN 978-0-201-63361-0 .
^ 萧萧. 怎样理解“组合优于继承”以及“OO的反模块化”,在这些方面FP具体来说有什么优势? . 2017-06-09 [2019-11-22 ] . (原始内容存档 于2020-02-04) (中文(简体)) .