Whats the difference between objects and data structures?
我一直在读《清洁代码:敏捷软件技术手册》,在第六章第95-98页中,它澄清了对象和数据结构之间的区别:
对象将其数据隐藏在抽象后面,并公开对该数据操作的函数。数据结构公开了它们的数据,没有有意义的函数。
对象公开行为并隐藏数据。这使得在不改变现有行为的情况下添加新类型的对象变得容易。这也使得向现有对象添加新行为变得困难。
数据结构公开数据,没有明显的行为。这使得向现有的数据结构中添加新的行为变得容易,但也使得向现有的函数中添加新的数据结构变得困难。
我有点困惑一些类是对象还是数据结构。比如说java.util中的hashmaps,它们是对象吗?(因为它的方法如put()、get(),我们不知道它们的内部工作原理)或者它们是数据结构?(我一直认为它是数据结构,因为它是一个地图)。
字符串也是,它们是数据结构还是对象?
到目前为止,我编写的大多数代码都是所谓的"混合类",它们试图充当对象和数据结构。还有什么关于如何避免它们的建议吗?
数据结构和类/对象之间的区别在Java中比在C++中更难解释。在C中,没有类,只有数据结构,它们只不过是类型字段和命名字段的"容器"。C++继承了这些"结构",所以你可以同时拥有"经典"的数据结构和"真实对象"。
在爪哇中,可以使用没有方法和只有公共字段的类"仿真"C风格的数据结构:
1 2 3 4 5 | public class VehicleStruct { public Engine engine; public Wheel[] wheels; } |
OOP背后的想法是隐藏数据并公开行为。它关注的是在不必知道是否有发动机或安装了多少车轮的情况下,您可以对车辆执行什么操作:
1 2 3 4 5 6 7 8 9 | public class Vehicle { private Details hidden; public void startEngine() { ... } public void shiftInto(int gear) { ... } public void accelerate(double amount) { ... } public void brake(double amount) { ... } } |
注意,
现在,按照"封装规则",您可以理解隐藏数据只是将字段设为私有字段,并向
1 2 3 4 5 6 7 8 | public class VehicleStruct { private Engine engine; private Wheel[] wheels; public Engine getEngine() { return engine; } public Wheel[] getWheels() { return wheels; } } |
在他的书中,Bob叔叔认为通过这样做,你仍然有一个数据结构,而不是一个对象。您仍然只是将车辆建模为其零件的总和,并使用方法公开这些零件。它本质上与带有公共字段的版本相同,并且是一个普通的老C
当你把这两种方法混合在一起时,例如将
关于散列图和字符串的问题有点棘手,因为这些问题的级别非常低,不适合您为应用程序编写的类。然而,使用上面给出的定义,您应该能够回答它们。
不要对可以使用映射实例替换数据结构感到困惑!
1 2 3 4 5 6 7 8 9 10 |
另一方面,
对象是类的实例。一个班可以从现实世界中模拟各种事物。这是一个抽象的东西(汽车,插座,地图,连接,学生,老师,你命名它)。
数据结构是以某种方式组织某些数据的结构。您可以使用不同于使用类的方式实现结构(这是您在不支持OOP的语言中所做的工作,例如,您仍然可以使用C语言实现数据结构)。
Java中的HashMap是一个使用基于哈希的实现对地图数据结构进行建模的类,这就是为什么它被称为Hash映射。
Java中的Socket是一个类,它不建模数据结构,而是其他的(套接字)模型。
我相信这就是罗伯特。C.马丁试图传达:
数据结构是简单地充当结构化数据容器的类。例如:
1 2 3 4 |
另一方面,对象用于创建抽象。抽象被理解为:
a simplification of something much more complicated that is going on under the covers The Law of Leaky Abstractions, Joel on Software
因此,对象隐藏了其所有基础,只允许您以简化的方式操作其数据的本质。例如:
1 2 3 4 5 6 7 8 | public interface Point { double getX(); double getY(); void setCartesian(double x, double y); double getR(); double getTheta(); void setPolar(double r, double theta); } |
我们不知道该点是如何实现的,但我们知道如何使用它。
正如我所看到的,罗伯特·马丁试图传达的是,对象不应该通过getter和setter公开数据,除非它们的唯一目的是充当简单的数据容器。这样的容器的好例子可能是Java bean、实体对象(来自DB实体的对象映射)等。
然而,Java集合框架类并不是他所指的一个很好的例子,因为它们并没有真正公开其内部数据(这在很多情况下是基本数组)。它提供了抽象,让您检索它们包含的对象。因此(在我的POV中)它们适合"对象"类别。
原因是由你从书中添加的引语来说明的,但是还有更多的好理由避免暴露内部。例如,提供getter和setter的类会违反demeter的法律。此外,了解某个类的状态结构(知道它拥有哪些getter/setter)会降低抽象该类实现的能力。还有很多这样的原因。
数据结构只是一种抽象,一种表示数据的特殊方式。它们只是人为构造,有助于降低高层的复杂性,即不在底层工作。一个对象可能意味着相同的事情,但是对象和数据结构之间的主要区别是对象可能抽象任何东西。它还提供行为。数据结构没有任何行为,因为它只是保存内存的数据。
库类(如map、list等)是表示数据结构的类。它们实现并设置数据结构,以便通过创建它们的实例(即对象)在程序中轻松地使用它们。
数据结构实际上是一些数据的结构化表示。除了数据的结构和命名之外,它没有任何内置的"知识"。对象更为一般,实际上可以是系统中几乎任何一个为交互提供接口的实体,并且可以在不同的上下文中使用。具体来说,例如,传统的类对象可能包含数据和访问数据的合适方法,并且该数据可能是特定于对象实例(每个实例)或类级别的。
我不确定术语"混合类"是基于作为对象或数据结构的描述,因为类通常包含数据。所以这个术语似乎是多余的。
数据结构(DS)是一种抽象的表示结构拥有某些数据的方式。具有一些关键值对的HASMAP是Java中的数据结构。相关联的数组在php等中类似。对象比ds级别低一点。您的哈希图是一个数据结构。现在要使用哈希映射,您需要创建一个"对象",并使用Put方法向该对象添加数据。我可以有我自己的班级员工,他们有数据,因此是我的DS。但是要使用这个ds来做一些操作,比如查看雇员是男性还是女性同事,我需要一个雇员的实例并测试其性别属性。
不要将对象与数据结构混淆。
对象是类的实例。类可以定义该类的每个实例/对象继承的一组属性/字段。数据结构是组织和存储数据的一种方法。从技术上讲,数据结构是一个对象,但它是一个专门用来保存其他对象的对象(Java中的所有东西都是对象,甚至是原始类型)。
要回答您的问题,字符串是一个对象和数据结构。您创建的每个字符串对象都是string类的实例。一个字符串,如Java在内部表示的,本质上是一个字符数组,而数组是一个数据结构。
并非所有的类都是数据结构的蓝图,但是如果有任何意义的话,所有的数据结构在技术上都是对象,即类的实例(专门设计用于存储数据)。
您的问题被标记为Java,所以这里只引用Java。对象是Java中的EVE类;也就是说,Java中的所有对象都扩展对象和对象。
因此,所有的数据结构都是对象,但并非所有的对象都是数据结构。
区别的关键是术语封装。
在Java中创建对象时,最好将所有数据成员私有化。你这样做是为了保护他们不被任何人利用。
但是,您希望人们能够访问数据,有时可以更改数据。因此,您提供了名为访问器和赋值器的公共方法,以允许它们这样做,也称为getter和setter。另外,您可能希望他们以您选择的格式查看整个对象,这样您就可以定义一个ToString方法;这将返回一个表示对象数据的字符串。
结构略有不同。
这是一个班。
它是一个物体。
但它通常在另一个类中是私有的;因为节点在树中是私有的,树的用户不应该直接访问它。但是,在树对象内部,节点数据成员是公开可见的。节点本身不需要访问器和赋值函数,因为这些函数受树对象的信任和保护。
要研究的关键字:封装、可见性修饰符