java - Java中的抽象与封装

标签 java oop concept

Possible Duplicate:
Abstraction VS Information Hiding VS Encapsulation

我知道这个问题可能已经在这个论坛上被问过数千次了,甚至网络上也充满了关于这些概念的大量定义,但听起来都一样,而且都使用相同的技术词汇。例如以下定义

封装是将数据和对数据进行操作的代码绑定(bind)或包装成单个实体的过程。这使数据免受外部接口(interface)和误用的影响。考虑封装的一种方法是作为保护性包装器,防止代码和数据被包装器外部定义的其他代码任意访问。

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


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

现在这是让我一直困惑的部分。每当我想到抽象时,我想到的就是抽象类(可能是因为两者都有 Abstract 关键字)。上面的定义说抽象意味着隐藏数据并只显示所需的细节,但这就是我们在封装中已经在做的事情,对吧?那么有什么区别。我也没有得到什么是对象的外部 View ,它处理对象的外部 View

如果可能的话,有人可以通过一些现实生活中的示例或一些程序示例来更清楚地说明这一点。

最佳答案

OO Abstraction发生在类级别设计期间,目的是隐藏实现复杂性如何实现 API/设计/系统提供的功能,在某种意义上简化了“接口(interface)'来访问底层实现。

抽象的过程可以在类的越来越“更高”的层次(层)上重复,这样就可以在不增加代码的复杂性和每一层的理解的情况下构建大型系统。

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

同样,在设计自己的类时,您会希望尽可能地向其他人隐藏内部实现细节。

在Booch定义1中,OO封装是通过Information Hiding实现的,特别是围绕隐藏类实例拥有的内部数据(表示状态的字段/成员),通过以受控方式强制访问内部数据,并防止对这些字段进行直接的外部更改,以及隐藏任何内部实现类的方法(例如,将它们设为私有(private))。

例如,默认情况下可以将类的字段设置为 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 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
   }
}

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

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 
}

Re:抽象与抽象类

Abstract classes是促进类之间共性重用的类,但它们本身不能直接用 new() 实例化 - 抽象类必须是子类,并且只有 concrete(非抽象)子类可以实例化。 Abstractionabstract class 之间可能造成混淆的一个原因是,在 OO 的早期,继承被更多地用于实现代码重用(例如,与相关的抽象基类)。如今,composition is generally favoured over inheritance ,并且有更多的工具可用于实现抽象,例如通过接口(interface)、事件/委托(delegate)/函数、特征/混合等。

Re:封装与信息隐藏

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

引用维基百科:

In the more concrete setting of an object-oriented programming language, the notion is used to mean either an information hiding mechanism, a bundling mechanism, or the combination of the two.

例如在语句中

I've encapsulated the data access code into its own class

..封装的解释大致相当于Separation of ConcernsSingle Responsibility Principal (SOLID 中的“S”),并且可以说是重构的同义词。


[1] 一旦你看过 Booch 的 encapsulation cat picture你永远不会忘记封装——面向对象的分析和设计与应用程序的第 46 页, 第二版

关于java - Java中的抽象与封装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11965929/

相关文章:

java - 使用 lambda 迭代集合时使用 setter 方法

java - 需要编写一个 java 正则表达式,该表达式与 http 或 https 的 url 匹配,但不包含特定的文件扩展名

java - 除了易于调用之外,在 Java 中是否使用静态方法/函数?

c# - 在 C# 中使用静态函数和变量的困难

python - 在 Python 运行时创建对象

java - 如何理解java中递归的概念?

java - 实现另一个接口(interface)的解决方法接口(interface)

java - 细胞模型输出未显示

database - 规范化的类设计是否会导致规范化的数据库设计

php - 404 服务器重定向,还是其他一些方法?