Java中的抽象与封装

San*_*mar 84 java oop concept

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

我知道这个问题可能已经在这个论坛上被问了几千次,甚至net也充满了关于这些概念的许多定义,但所有声音都相同,并且都使用相同的技术词汇.例如以下定义

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

我从上面的定义中理解的是创建变量,将它们标记为私有并为这些变量生成getter-setter,并使用object来访问那些getter和setter.这样,数据就隐藏在对象内部,只能通过对象访问.希望我是对的.


抽象是Java中的过程,用于隐藏某些细节并仅显示对象的基本特征.换句话说,它处理对象(界面)的外部视图.

现在这是让我困惑的部分.每当我想到抽象时,我想到的东西就是抽象类(可能因为它们都有Abstract关键字).上面的定义说抽象意味着隐藏数据并且只显示所需的细节,但这是我们在封装中已经做的事情吗?然后有什么区别.此外,我没有得到对象的侧视图,它处理对象的外部视图.

有人可以用一些现实生活中的例子,或者如果可能的话,用一些程序化的例子来说明这一点.

Stu*_*tLC 87

OO抽象过程中一流水平的设计时,以应用为目标隐藏实现复杂是如何在由API /设计/系统提供的功能得以实施,在一定意义上简化了"接口"来访问底层实现.

这个过程可以在越来越"更高"的抽象层次(层)上重复,这使得可以在更高层的情况下构建大型系统而不增加代码和理解的复杂性.

例如,Java开发人员可以利用FileInputStream的高级功能而无需担心它是如何工作的(即文件句柄,文件系统安全检查,内存分配和缓冲将在内部进行管理,并且对消费者隐藏).这允许实现FileInputStream更改,并且只要API(接口)FileInputStream保持一致,针对先前版本构建的代码仍然可以工作.

同样,在设计类时,您需要尽可能地隐藏其他人的内部实现.

在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;
}
Run Code Online (Sandbox Code Playgroud)

已应用字段封装的示例:

class Bar {
   // Improvement - access restricted only to this class
   private int encapsulatedPercentageField;

   // The state of Bar (and its fields) can now be changed in a controlled manner
   public void setEncapsulatedField(int percentageValue) {
      if (percentageValue >= 0 && percentageValue <= 100) {
          encapsulatedPercentageField = percentageValue;
      }
      // else throw ... out of range
   }
}
Run Code Online (Sandbox Code Playgroud)

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

class Baz {
   private final int immutableField;

   public void Baz(int onlyValue) {
      // ... As above, can also check that onlyValue is valid
      immutableField = onlyValue;
   }
   // Further change of `immutableField` outside of the constructor is NOT permitted, even within the same class 
}
Run Code Online (Sandbox Code Playgroud)

回复:抽象与抽象类

抽象类是促进类之间的共同性的重用类,但其本身不能直接与被实例化new()-抽象类必须被继承,并且只有concrete(非抽象)子类可以被实例化.可能是OO 之间混淆的Abstraction一个原因abstract class是,在OO的早期,继承被更多地用于实现代码重用(例如,使用相关的抽象基类).如今,组合通常比继承受欢迎,并且有更多工具可用于实现抽象,例如通过接口,事件/委托/函数,特征/混合等.

Re:封装与信息隐藏

封装的含义似乎随着时间的推移而演变,并且在最近的时候,encapsulation在确定将哪些方法,字段,属性,事件等捆绑到类中时,通常也在更一般的意义上使用.

引用维基百科:

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

例如,在声明中

我已将数据访问代码封装到自己的类中

..的解释封装是大致相当于关注点分离单一职责委托(以下简称"S"在固体),并且可以说是被用作用于重构的同义词.


[1] 一旦你看到Booch的封装猫图片,你将永远无法忘记封装 - 面向对象分析和应用程序设计的第46页,第二版


小智 50

简单来说:在决定实施什么时,你会做抽象.隐藏已实现的内容时进行封装.


Bri*_*new 36

抽象是指识别共性并减少必须在代码的不同级别使用的功能.

我可能Vehicle上课了.A Car将来自a Vehicle,a Motorbike.我可以询问每个Vehicle车轮,乘客等的数量,并且这些信息已经被抽象出来并被识别为CarsMotorbikes.

在我的代码往往只处理Vehicles通过常用的方法go(),stop()等等.当我后来添加一个新的车辆类型(例如Scooter)我的大部分代码将继续无视这一事实,并执行Scooter有关单独的担忧Scooter特殊性.