java - 对象和数据结构之间的区别是什么?

我一直在读这本书,在第六章第95-98页,它澄清了对象和数据结构之间的区别:
对象将其数据隐藏在抽象后面,并公开对该数据操作的函数。数据结构公开了它们的数据,没有有意义的函数。
对象公开行为并隐藏数据。这使得在不改变现有行为的情况下添加新类型的对象变得容易。这也使得向现有对象添加新行为变得困难。
数据结构公开数据,没有明显的行为。这使得向现有的数据结构中添加新的行为变得容易,但也使得向现有的函数中添加新的数据结构变得困难。
我有点困惑一些类是对象还是数据结构。比如说java.util中的hashmaps,它们是对象吗?(因为它的方法如put()、get(),我们不知道它们的内部工作原理)或者它们是数据结构?(我一直认为它是数据结构,因为它是一个地图)。
字符串也是,它们是数据结构还是对象?
到目前为止,我编写的大多数代码都是所谓的“混合类”,它们试图充当对象和数据结构。还有什么关于如何避免它们的建议吗?


最佳答案:

数据结构和类/对象之间的区别在Java中比在C++中更难解释。在C中,没有类,只有数据结构,它们只不过是类型字段和命名字段的“容器”。C++继承了这些“结构”,所以你可以同时拥有“经典”的数据结构和“真实对象”。
在爪哇中,可以使用没有方法和只有公共字段的类“仿真”C风格的数据结构:

public class VehicleStruct
{
    public Engine engine;
    public Wheel[] wheels;
}

VehicleStruct的用户知道车辆的部件,可以直接与这些部件交互。行为,即函数,必须在类之外定义。这就是为什么很容易更改行为:添加新函数不需要更改现有代码。另一方面,更改数据实际上需要更改与VehicleStruct交互的每个函数。它违反了封装!
OOP背后的想法是隐藏数据并公开行为。它关注的是在不必知道是否有发动机或安装了多少车轮的情况下,您可以对车辆执行什么操作:
public class Vehicle
{
    private Details hidden;

    public void startEngine() { ... }
    public void shiftInto(int gear) { ... }
    public void accelerate(double amount) { ... }
    public void brake(double amount) { ... }
}

请注意,Vehicle可能是摩托车、汽车、卡车或坦克——您不需要知道详细信息。更改数据很容易——类外没有人知道数据,因此不需要更改类的用户。改变行为是困难的:当一个新的(抽象的)函数添加到类中时,必须调整所有子类。
现在,遵循“封装规则”,您可以理解隐藏数据,只需将字段设为私有字段,并向VehicleStruct添加访问器方法:
public class VehicleStruct
{
    private Engine engine;
    private Wheel[] wheels;

    public Engine getEngine() { return engine; }
    public Wheel[] getWheels() { return wheels; }
}

在他的书中,Bob叔叔认为通过这样做,你仍然有一个数据结构,而不是一个对象。您仍然只是将车辆建模为其零件的总和,并使用方法公开这些零件。它本质上与带有公共字段的版本相同,并且是一个普通的旧Cstruct——因此是一个数据结构。隐藏数据和公开方法不足以创建一个对象,您必须考虑这些方法是实际公开行为还是只公开数据!
当你把这两种方法混合在一起时,例如,把getEngine()startEngine()一起暴露出来,你就会得到一个“混合”。我手头没有马丁的书,但我记得他根本不推荐混合动力车,因为你最终会遇到两个世界中最糟糕的:数据和行为都难以改变的对象。
关于散列图和字符串的问题有点棘手,因为这些问题的级别非常低,不适合为应用程序编写的类。然而,使用上面给出的定义,您应该能够回答它们。
aHashMap是一个对象。它向您公开它的行为,并隐藏所有令人讨厌的散列细节。告诉它putget数据,而不关心使用的是哪个哈希函数,有多少“bucket”,以及如何处理冲突。实际上,您只通过HashMap接口使用Map,这是抽象和“真实”对象的很好指示。
不要对可以使用映射实例替换数据结构感到困惑!
// A data structure
public class Point {
    public int x;
    public int y;
}

// A Map _instance_ used instead of a data structure!
Map<String, Integer> data = new HashMap<>();
data.put("x", 1);
data.put("y", 2);

另一方面,aString几乎是一个字符数组,并且不会试图隐藏太多。我想有人可以称之为数据结构,但老实说,我不确定是否可以通过这种或那种方式获得很多。