数据结构和类/对象之间的区别在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
put
get
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);
另一方面,A几乎是一系列字符,并且不会试图隐藏太多。我想人们可以称之为数据结构,但说实话,我不确定是否能以这种或那种方式获得很多东西。String