Hoo*_*lum 39 java language-agnostic oop object data-structures
我一直在读" 清洁代码:敏捷软件工艺手册 "一书,在第六章第95-98页中,它阐明了对象和数据结构之间的区别:
对象将其数据隐藏在抽象之后,并公开对该数据进行操作的函数.数据结构公开其数据并且没有有意义的功能.
对象公开行为并隐藏数据.这使得在不改变现有行为的情况下添加新类型的对象变得容易.它还使得很难向现有对象添加新行为.
数据结构公开数据并且没有重要行为.这使得向现有数据结构添加新行为变得容易,但却难以向现有函数添加新数据结构.
对于某些类是对象还是数据结构,我有点困惑.比如java.util中的HashMaps,它们是对象吗?(因为它的方法如put(),get(),我们不知道它们的内部工作原理)还是数据结构?(我一直认为它是数据结构,因为它是一个Map).
字符串也是数据结构或对象吗?
到目前为止,我编写的大多数代码都是所谓的"混合类",它们也试图充当对象和数据结构.关于如何避免它们的任何提示?
Fer*_*yer 32
数据结构和类/对象之间的区别在Java中比在C++中更难解释.在C中,没有类,只有数据结构,它们只不过是类型和命名字段的"容器".C++继承了这些"结构",因此您可以拥有"经典"数据结构和"真实对象".
在Java中,您可以使用没有方法且只有公共字段的类来"模拟"C风格的数据结构:
public class VehicleStruct
{
public Engine engine;
public Wheel[] wheels;
}
Run Code Online (Sandbox Code Playgroud)
用户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) { ... }
}
Run Code Online (Sandbox Code Playgroud)
注意Vehicle
摩托车,汽车,卡车或坦克怎么样 - 你不需要知道细节.更改数据很容易 - 类外的人都不知道数据,因此不需要更改类的用户.改变行为很困难:当向类中添加新的(抽象)函数时,必须调整所有子类.
现在,遵循"封装规则",您可以理解将数据隐藏为仅将字段设为私有并将访问器方法添加到VehicleStruct
:
public class VehicleStruct
{
private Engine engine;
private Wheel[] wheels;
public Engine getEngine() { return engine; }
public Wheel[] getWheels() { return wheels; }
}
Run Code Online (Sandbox Code Playgroud)
在他的书中,鲍勃叔叔争辩说,通过这样做,你仍然有一个数据结构,而不是一个对象.您仍然只是将车辆建模为其零件的总和,并使用方法公开这些零件.它与具有公共字段和普通旧C的版本基本相同struct
- 因此是数据结构.隐藏数据和公开方法不足以创建对象,您必须考虑方法是否实际暴露行为或仅仅是数据!
当你混合使用这两种方法时,例如getEngine()
与之一起曝光startEngine()
,你就会得到一个"混合".我手头没有马丁的书,但我记得他根本不推荐混合动力车,因为你最终得到了两个世界中最糟糕的:数据和行为都很难改变的对象.
您对HashMaps和字符串的问题有点棘手,因为它们的级别相当低,并且在您为应用程序编写的类中不太适合.尽管如此,使用上面给出的定义,您应该能够回答它们.
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);
Run Code Online (Sandbox Code Playgroud)
String
另一方面,A 几乎是一个字符数组,并不试图隐藏它.我想有人可以称之为数据结构,但说实话,我不确定是否可以通过这种方式获得更多.
我相信,这就是罗伯特。C. 马丁试图传达:
数据结构是简单地充当结构化数据容器的类。例如:
public class Point {
public double x;
public double y;
}
Run Code Online (Sandbox Code Playgroud)另一方面,对象用于创建抽象。一个抽象被理解为:
对隐藏的更复杂的事情的简化The Law of Leaky Abstractions, Joel on Software
因此,对象隐藏了它们的所有基础,只能让您以简化的方式操作其数据的本质。例如:
public interface Point {
double getX();
double getY();
void setCartesian(double x, double y);
double getR();
double getTheta();
void setPolar(double r, double theta);
}
Run Code Online (Sandbox Code Playgroud)
我们不知道 Point 是如何实现的,但我们知道如何使用它。