OOP设计:责任在哪里?

时间:2012-09-04 14:39:16

标签: oop design-patterns

我有一个简单的对象列表。我想为每个对象计算一种哈希值,用于对列表进行排序。

我的问题是:谁负责计算哈希?

1 /列表

因为哈希方法特定于列表,并应用于每个对象。 对象只是对象,他们不知道排序和散列。

2 /每个对象

因为对象是最佳候选者,因为他拥有所有数据。 这可以通过其他人无法访问的内部数据来计算。

3 /另一个挑战者?就像列表和对象之间的控制器一样?

2 个答案:

答案 0 :(得分:4)

定义所用等价概念的类。

如果一个对象定义了一个通用的相等概念,那么它应该定义一个与之对应的哈希码,作为该工作的一部分。

毕竟,正是该类“知道”Equals()isEqual()areEqual==或其他任何内容的定义。当a == b表示hash(a) == hash(b)时,它是唯一可以这样做的类。

但是,如果另一个类定义了相等的概念,(也许是为了不同的方式使用不同的方法,其中人们可能认为字符串相同或不同的不同方式是一个典型的例子)那么该类必须定义哈希码类似的原因。

.NET表示这种责任链接,作为一个例子。在.NET中,所有对象都有Equals()。这是否是一件好事是值得商榷的(有些人更喜欢C ++方法,其中一个对象不需要有任何与另一个对象相等的感觉),但是一旦完成它确实有意义所有对象也有GetHashCode(),因为一个与另一个之间的联系。 .NET也有IEqualityComparer<T>IEqualityComparer,它定义了一个类对特定的非内置平等感负责的方法。在这里,对一个人负责也需要对另一个负责。

现在。哪个更好?

那么,如果在给定的情况下对“等于”意味着什么有绝对明显的意义,它应该由类来处理:相同坐标或相同复数的两个表示或指的是相同的现实世界对象,大多数时候应该被认为是平等的。这样就可以默认使用了。

如果在给定的容器类型的上下文中有一个非常明显的等于什么意义的意义,那么应该在那里应用。

否则应该有一个定义它的连接器。因此,我们可以很好地区分这些问题。

然而,我们可以非常整齐地将三者结合在一起。我们定义一个默认连接器。它的实现仅传递调用以获取哈希码或测试与对象上定义的相等的相等性。

我们定义任何通用哈希表,哈希集等,以便始终使用连接器,默认为构造或默认模板参数(如果语言具有允许这种类型的通用/模板方法,例如,C ++和C#(例如没有),因此默认情况下我们使用此默认连接器。

在为特定目的定义依赖于特定概念视图的特殊用途集合类型时,我们从其中一个集合构建它,覆盖连接器。

这条规则的另一面是,如果你没有为所有可等对象提供一个定义的方法来给出一个哈希码(例如你有一个==覆盖机制,但是没有对一个{的深度支持{1}}),然后拥有以使用连接器方法。请注意,虽然C ++例如确实有GetHashCode(),但它不知道如何拥有给定对象的那种支持。因此,STL必须具有==并且对于它的开箱即用默认值的支持非常有限。

答案 1 :(得分:1)

您的对象应包含计算哈希码值的方法。

在java中,Object是所有类的父类,它有hashCode()方法(Java Object)。这意味着Java中的每个对象都有此方法来计算此方法。背后的原因纯粹是对信息的封装。 hashCode()是在类属性上执行的,因此它应该放在特定的类中。