Java中的抽象与封装

可能重复:
抽象VS信息隐藏VS封装

我知道这个问题在这个论坛上可能已经有好几千次的问题了,甚至networking上也充斥着很多关于这些概念的定义,但是听起来都是一样的,都使用相同的技术词汇。 例如下面的定义

封装是将数据和对数据进行操作的代码绑定或包装成一个实体的过程。 这样可以保证数据不受外界接口和误用。 考虑封装的一种方法是作为一种保护包装,防止代码和数据被包装器外部定义的其他代码任意访问。

我从上面的定义中明白的是,创buildvariables,将它们标记为private,并为这些variables生成getter-setter,并使用object访问这些getter和setter。 这样数据就隐藏在对象内部,只能通过对象访问。 希望我是对的


抽象是Java中抽象的过程,用来隐藏某些细节,只显示对象的本质特征。 换句话说,它处理对象(接口)的外部视图。

现在这是总让我困惑的部分。 每当我想到抽象概念时,我想到的就是Abstract类(可能是因为两者都有Abstract关键字)。 上面的定义是说抽象意味着隐藏数据,只显示需要的细节,但这就是我们已经在封装的权利? 那么有什么区别。 我也没有得到什么是对象的外侧视图处理对象的外部视图

有人能请一些真实生活的例子或一些程序化的例子,如果可能的话更多的照顾这个。

面向对象抽象层次devise是为了隐藏实现 API /devise/系统提供的function的实现复杂性的目的,从某种意义上简化了访问底层实现的“接口”。

这个过程可以在越来越高的层次(层次)上重复,这样就可以在不增加代码和理解的复杂性的情况下构build大型系统。

例如,Java开发人员可以利用FileInputStream的高级function,而不必关心它的工作原理(即文件句柄,文件系统安全检查,内存分配和缓冲将在内部pipe理,并且从消费者隐藏)。 这允许FileInputStream的实现被改变,并且只要到FileInputStream的API(接口)保持一致,针对先前版本构build的代码仍将工作。

同样,在devise你的类的时候,你也会尽可能的隐藏内部的实现。

在Booch定义1中OO封装是通过信息隐藏来实现的,特别是通过隐藏类实例拥有的内部数据(字段/表示状态的成员),通过以受控的方式强制访问内部数据,以及防止直接,这些领域的外部变化,以及隐藏类的任何内部实现方法(例如通过使它们变为私有)。

例如,默认情况下,类的字段可以是private的,并且只有当需要外部访问这些字段时, get()和/或set() (或Property )才能从类中公开。 (在现代OO语言中,字段可以被标记为readonly / final / immutable ,这进一步限制了变化,甚至在课程内)。

没有信息隐藏的例子(坏习惯)

 class Foo { // BAD - NOT Encapsulated - code external to the class can change this field directly // Class Foo has no control over the range of values which could be set. public int notEncapsulated; } 

已应用字段封装的示例

 class Bar { // Improvement - access restricted only to this class private int encapsulated; // The state of Bar (and its fields) can now be changed in a controlled manner public void setEncapsulatedField(int newValue) { if (newValue < 100) { encapsulated = newValue; } // else throw ... out of range } } 

字段的不可变/仅构造函数初始化的示例

 class Baz { private final int onlyValue; public void Baz(int immutableValue) { // ... can check that immutableValue is valid onlyValue = immutableValue; } // Further change of `onlyValue` outside of the constructor is NOT permitted // even within the same class } 

回复:抽象与抽象类

抽象类是促进类之间通用性重用的类,但是它们本身不能直接用new()实例化 – 抽象类必须被子类化,只有concrete (非抽象的)子类可以被实例化。 Abstractionabstract class之间可能混淆的一个原因是,在OO的早期,inheritance被更多地用于实现代码重用(例如与相关的抽象基类)。 现在, 构图通常比inheritance更受欢迎 ,并且有更多的工具可以实现抽象,比如通过接口,事件/委托/function,特性/混合等。

回复:封装vs信息隐藏

最近,当确定哪些方法,字段,属性,事件等被bundle到一个类中时, encapsulation通常也被用在更一般的意义上。

引用维基百科:

在更具体的面向对象编程语言设置中,这个概念被用来表示信息隐藏机制,捆绑机制或者两者的组合。

例如,在“我已经将数据访问代码封装到它自己的类中”的声明中封装的解释大致等同于“ 关注分离”主体(SOLID中的S),并且可以被用作重构。


[1] 一旦你看到Booch的封装猫的图片,你永远不会忘记封装 – 面向对象的分析和devise与应用程序,第2版

简而言之:在决定要实施什么的时候你要抽象。 隐藏你已经实现的东西的时候你要封装。

抽象是关于在代码的不同级别上确定共同点并减less要使用的function。

例如我可能有一个Vehicle类。 一辆Car将来自一辆VehicleMotorbike也会如此。 我可以问Vehicle的轮子数量,乘客等,这些信息已被抽象和识别为常见的CarsMotorbikes

在我的代码中,我经常可以通过常用的方法go()stop()等来处理Vehicles 。当我稍后添加一个新的Vehicletypes(例如Scooter )时,我的大部分代码将不会忽略这个事实,单独Scooter担心Scooter特殊性。