一尘不染

对象和数据结构之间有什么区别?

java

我一直在阅读《
清洁代码:敏捷软件技巧手册》

,在第六章第95-98页中阐明了对象和数据结构之间的区别:

  • 对象将其数据隐藏在抽象之后,并公开对该数据进行操作的函数。数据结构公开其数据,并且没有有意义的功能。

  • 对象公开行为并隐藏数据。这使得在不更改现有行为的情况下添加新的对象变得容易。这也使得很难向现有对象添加新行为。

  • 数据结构公开数据并且没有重大行为。这使向现有数据结构添加新行为变得容易,但向现有功能添加新数据结构变得困难。

对于某些类是对象还是数据结构,我有些困惑。例如说java.util中的HashMap,它们是对象吗?(由于其诸如put(),get()之类的方法,我们不知道它们的内部工作原理)还是它们的数据结构?(我一直认为它是数据结构,因为它是Map)。

字符串也是如此,它们是数据结构还是对象?

到目前为止,我编写的大多数代码都是所谓的“混合类”,它们试图同时充当对象和数据结构。关于如何避免它们的任何提示?


阅读 794

收藏
2020-12-03

共1个答案

一尘不染

在Java中比在C 中更难解释数据结构和类/对象之间的区别。在C语言中,没有类,只有数据结构,无非是类型字段和命名字段的“容器”。C
继承了这些“结构”,因此您可以同时拥有“经典”数据结构和“真实对象”。

在Java中,您可以使用没有方法并且只有公共字段的类“模拟” 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; }
}

鲍勃叔叔在他的书中认为,通过这样做,您仍然具有数据结构而不是对象。您仍然只是将车辆建模为零件的总和,并使用方法公开这些零件。它与具有公共字段和普通旧C的版本基本相同struct-因此是数据结构。隐藏数据和公开方法不足以创建对象,您必须考虑这些方法实际上是公开
行为 还是仅公开数据!

当您将两种方法混合使用时(例如getEngine()与一起使用)startEngine(),最终会出现“混合”现象。我手头没有马丁书,但我记得他根本不推荐混合动力车,因为最终会遇到两全其美的局面:数据和行为都难以改变的对象。

您对HashMaps和Strings的问题有些棘手,因为它们的级别很低,并且不太适合您要为应用程序编写的类。但是,使用上面给出的定义,您应该能够回答它们。

A
HashMap是一个对象。它向您展示其行为,并隐藏所有令人讨厌的哈希详细信息。你告诉它putget数据,并不在乎其散列函数被使用,多少个“桶”有,而且冲突的处理方式。实际上,您HashMap仅通过其Map接口使用,这很好地表示了抽象和“真实”对象。

不要混淆,可以使用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);

String另一方面,A
几乎是一个字符数组,并且不会尝试将其隐藏得太多。我想可以将其称为数据结构,但是老实说,我不确定是否可以通过一种方法或其他方法获得大量收益。

2020-12-03