- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
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
(非抽象)子类可以实例化。 Abstraction
和 abstract 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 Concerns或 Single Responsibility Principal (SOLID 中的“S”),并且可以说是重构的同义词。
[1] 一旦你看过 Booch 的 encapsulation cat picture你永远不会忘记封装——面向对象的分析和设计与应用程序的第 46 页, 第二版
关于java - Java中的抽象与封装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11965929/
我需要使用封装打印3个变量,并且无法修改主类。 主类声明变量[汽缸、制造商、所有者],并希望使用如下参数创建和打印一个对象: System.out.println (new Vehicle (cyli
我正在研究“Beginning Ruby”这本书,在我进行封装之前一切都进行得很顺利。我明白这段代码在做什么,我只是不知道为什么要用这些方法设置它。 对于那些感兴趣的人 this is the lin
所以我一直在研究面向对象的完整开发 JavaScript 实践,并对以下示例感到好奇。 据我了解,(这对我来说很有意义)以下“ secret ”字段是“私有(private)”的: var MyObj
在面向对象程式设计方法中,封装(英语:Encapsulation)是指,一种将抽象性函式接口的实作细节部份包装、隐藏起来的方法。 封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代
封装 被定义为 把一个或多个项目封闭在一个物理的或者逻辑的包中 。在面向对象程序设计方法论中,封装是为了防止对实现细节的访问。 抽象和封装是面向对象程序设计的相关特性。抽象允许相关信息可
今天我读了一本书,作者写道,在一个设计良好的类中,访问属性的唯一方法是通过其中一个类方法。这是一个被广泛接受的想法吗?为什么封装属性如此重要?不做会有什么后果?我早些时候在某处读到这可以提高安全性或类
今天我接受了软件工程职位的面试。我已经从 stackoverflow 中阅读了很多关于面试的内容。他们向我询问了与 OOP 相关的正常情况。但他们也问我这些: 没有继承就可以封装吗? 没有继承就可以抽
我正在制作一个简单的网站,并编写了gradle构建脚本,该脚本将执行诸如lint并最小化css / html / js之类的事情。 在这一阶段,我刚刚完成了正在运行的CSS,但是只是初始的非结构化格式
下面的幻灯片是指 C++ 语言,它说 "encapsulation is about ensuring the user uses our ADT in a safe way" 但是,如果他可以访问我
尝试设置一个 Person 类 我在尝试将信息封装在类中以使其不会被意外更改时遇到了问题。除了当我尝试使用 setter/getters 进行封装时,该类工作得非常好。我认为问题是这些方法最终会互相循
面向对象的概念:封装、数据抽象和数据隐藏是3个不同的概念,但彼此之间非常相关。所以我很难通过阅读互联网上的信息来完全理解这些概念。一个地方可用的信息与互联网上另一个地方的信息相矛盾。有人可以指导我阅读
我被封装困住了。在我看来,好像我已经按照规则做了一切,但仍然不起作用。虽然我知道我错过了一些东西。我正在使用 Eclipse。 我想要通过创建一副标准 52 张卡片来进行一些练习,并尝试我学到的新东西
在java中,要获取映射中的所有键,我们可以使用方法keySet。但我想知道为什么方法名称不只是 keys ?名称 Set 是否会泄露有关实现的详细信息? 据我了解,Java 是静态类型语言,名称中包
我正在尝试找出如何防止应用程序中的页面变量被全局定义。我想出了一些方法,但我想知道是否有人们使用的通用标准方法。 我使用这种方法得到了我的插件设计模式:http://www.virgentech.co
我有一个 tcp 连接,我想在服务器类的 HandleConnectionAsync 方法中保持打开状态。它将从客户端接收持续更新。 private async void HandleConnecti
这是我类(class)的一个小样本: #include #include using std::string; using std::vector; struct Book { string
我想要类似下面的代码: class Foo{ public: void update() { for( auto dataModifier : _dataModifierLis
这已经困扰我一段时间了,所以我问了一个同事他是否能理解它,现在我来了;) 为什么可以在依赖属性的 PropertyChangedCallback 中访问持有类的私有(private)成员? 让我通过这
我知道封装意味着一个对象不应该直接访问不同对象的成员……但我猜它与公共(public)领域有关?我假设公共(public)方法不会破坏封装..?我只是在这里不清楚,很高兴得到任何解释。 最佳答案
我就废话不多说了,大家还是直接看代码吧~ ? 1
我是一名优秀的程序员,十分优秀!