简体   繁体   English

Pharo Smalltalk中=和==有什么区别?

[英]What is the difference between = and == in Pharo Smalltalk?

What is the difference between = and == in Pharo Smalltalk? Pharo Smalltalk中===什么区别? What are they named, one isEqual and the other? 他们叫什么名字,一个是isEqual ,另一个是?

= ~=    equality / inequality (deep)
== ~~   equality / inequality (shallow)

Yes, == is identity and it uses a primitive to compare if pointers point to the same address (ie same object). 是的, ==是标识,如果指针指向相同的地址(即相同的对象),它将使用原语进行比较。

= is equality, meaning that two objects are equal, although they may be 2 different objects. =是相等的,表示两个对象相等,尽管它们可能是2个不同的对象。 By default = uses == , but it can be reimplemented. 默认情况下, =使用== ,但是可以重新实现。 Also when you reimplement = it's advised to also reimplement hash so hashed collections won't go crazy 另外,当您重新实现=建议也重新实现hash这样散列的集合就不会发疯

One important thing to take into account is that = is not only used explicitly when your code compares two objects. 要考虑的一件事是=不仅在代码比较两个对象时显式使用。 The message = is also implicitly used by many other messages such as: includes: , <= , >= , remove: , keyAtValue: , indexOf: , upTo: , peekFor: , occurrencesOf: , add: (in Set ), at: (and friends at:ifAbsent: , at:ifAbsentPut: , etc.), and many others. 该消息=隐式地使用许多其他消息,例如: includes:<= >=remove:keyAtValue: indexOf: upTo:peekFor: occurrencesOf: add: (在Set ), at: (以及at:ifAbsent:at:ifAbsentPut:等的朋友),等等。

This means that when you redefine = in your class you should make sure that 这意味着当您在类中重新定义= ,应确保

  1. Your implementation of = is robust (eg, banana = car gives no error) and 您对=实现是可靠的(例如, banana = car没有错误)并且
  2. Every time you redefine = you also redefine hash . 每次您重新定义=您还重新定义了hash

The reason for the first condition is to be able to compare any two objects without the sender having to take any special care before sending the = message. 第一个条件的原因是能够比较任何两个对象,而发送方在发送=消息之前不必特别注意。

The reason for the second is that if in the future your objects are used in a hashed collection ( Set , Dictionary , Bag , etc.) they will honor the important invariant required by these entities 第二个原因是,如果将来将您的对象用于哈希集合( SetDictionaryBag等),它们将兑现这些实体所需的重要不变式

      IF a = b THEN a hash = b hash

And given that it is a very good practice to make sure that hash values are SmallIntegers , one could say 考虑到确保hash值是SmallIntegers是一个很好的做法,可以说

      IF a = b THEN a hash == b hash

In other words, every time two objects are considered to be equal their hash values should be granted to be identical . 换句话说,每当两个对象被认为相等时,它们的hash值应被授予相同


Naming 命名

When reading an expression involving = such as a = b one says a is equal to b or a equals b . 读取涉及=的表达式(例如a = ba 等于 ba 等于 b

When reading a == b Smalltalkers say a and b are the same object , or a is equal equal to b or a is identical to a or even a is equal-equal to b . 读取时a == b Smalltalkers说a b 是相同的对象 ,或a 是等于等于 ba 是相同的 a或甚至a 等于-等于 b

Further comments 进一步的评论

The = message is domain specific, meaning that it is up to you to decide when two Smalltalk objects represent the very same object in your application. =消息是特定于域的,这意味着您可以决定何时两个Smalltalk对象代表应用程序中的同一对象。

The == message is a system feature, meaning that it is implemented by the Virtual Machine (VM) which verifies that the objects being compared occupy the very same location in memory. ==消息是系统功能,这意味着它由虚拟机(VM)实施,该虚拟机验证要比较的对象在内存中的位置是否完全相同。 In other words, two variables a and b are equal-equal when they are bound to the very same object. 换句话说,两个变量ab在绑定到同一对象时是相等的

Examples 例子

a := 'This String'.
b := 'This' , ' ', 'String'.
a == b "false".
a = b "true"

f := 2 / 3.
g := 2 / 3.
f = g "true".
f == g "false"

Generally speaking SmallInteger s which are = are also == because the VM encodes them in a special way. 一般来说, = SmallInteger也是==因为VM会以特殊方式对其进行编码。

n := 3 + 4.
m := 2 + 5.
n = m "true".
n == m "true".

Another interesting case happens with instances of the class Symbol 另一个有趣的情况发生在Symbol类的实例上

s := #symbol.
t := 'symbol' asSymbol.
s = t "true".
s == t "true!"

This happens because the Symbol class makes sure that no two instances with the same underlying string will ever exist in the environment. 发生这种情况是因为Symbol类确保环境中不会存在两个具有相同基础字符串的实例。

TL;DR: = : "equals", == : "same as" TL; DR:=:“等于”,==:“与”相同

In Object>>#= 在对象中>>#=

= anObject 
"Answer whether the receiver and the argument represent the same 
object. If = is redefined in any subclass, consider also redefining the 
message hash."

^self == anObject 

In ProtoObject>>#== 在ProtoObject中>>#==

== anObject "Primitive. Answer whether the receiver and the argument are the same object (have the same object pointer). Do not redefine the message == in any other class! Essential. No Lookup. Do not override in any subclass. See Object documentation whatIsAPrimitive." == anObject“ Primitive。回答接收方和参数是否是同一对象(具有相同的对象指针)。不要在任何其他类中重新定义消息==!必不可少。没有查找。请勿在任何子类中覆盖。请参见对象文档whatIsAPrimitive。”

<primitive: 110>
self primitiveFailed

So, you can override = but not ==. 因此,您可以覆盖=,但不能覆盖==。

FWIW ProtoObject subclass: #Object FWIW ProtoObject subclass: #Object

An example of an #= override is #=替代的示例是

´= aBag "Two bags are equal if (a) they are the same 'kind' of thing. (b) they have the same size. (c) each element occurs the same number of times in both of them" ´= aBag“如果两个袋子(a)是相同的'事物',(b)它们的大小相同。(c)每个元素在两个袋子中出现相同的次数相同,则两个袋子相等。”

(aBag isKindOf: Bag) ifFalse: [^false].
self size = aBag size ifFalse: [^false].
contents associationsDo: [:assoc|
    (aBag occurrencesOf: assoc key) = assoc value
        ifFalse: [^false]].
^true`

Which, compared to Dictionary is a quite different beast (implementation of Bas in "interesting"). Dictionary相比,它是完全不同的野兽(Bas以“有趣”的方式实现)。

`Dictionary>>#= aDictionary "Two dictionaries are equal if (a) they are the same 'kind' of thing. (b) they have the same set of keys. (c) for each (common) key, they have the same value. See issue 16760 before changing" 'Dictionary >>#= aDictionary“如果两个字典相同,则(a)它们是相同的“种类”。(b)它们具有相同的键集。(c)每个(通用)键都具有相同的值。请参见问题16760,然后进行更改”

self == aDictionary ifTrue: [^true].
self species == aDictionary species ifFalse: [^false].
self size = aDictionary size ifFalse: [^false].
self associationsDo: [:assoc|
    (aDictionary at: assoc key ifAbsent: [^false]) = assoc value
        ifFalse: [^false]].
^true`

Interestingly they share the same hash method. 有趣的是,它们共享相同的hash方法。

`Collection>>#hash "Answer an integer hash value for the receiver such that, -- the hash value of an unchanged object is constant over time, and -- two equal objects have equal hash values" `Collection >>#hash“为接收方提供一个整数哈希值,以便-不变对象的哈希值随时间恒定,并且-两个相等的对象具有相等的哈希值”

| hash |

hash := self species hash.
self size <= 10 ifTrue:
    [self do: [:elem | hash := hash bitXor: elem hash]].
^hash bitXor: self size hash

` There is some smell with the self size <= 10, have fun tracing these calls. `自身大小<= 10时有些气味,跟踪这些呼叫很有趣。

For more basic objects, see these: 有关更多基本对象,请参见以下内容:

Magnitude >>#hash实现者

Have fun exploring. 祝您探索愉快。

In Spotter, hash #im or = #im gives you the implementers list, so you can quickly find out about them. hash #imhash #im= #im为您提供了实施者列表,因此您可以快速找到它们。

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM