2012-05-31 3 views
0

Например, в Javascript [1,2,3] === [1,2,3] и [1,2,3] == [1,2,3] оба являются ложными. Даже более простой случай пустого массива также является ложным. Причина в том, что массивы являются ссылочными типами, а [1,2,3] и [1,2,3] различны в качестве ссылок. Javascript не уникален в этом отношении, и почти каждый язык реализует равенство как ссылочное равенство, за исключением основных типов, таких как целые числа и, возможно, некоторые встроенные типы.Что так сильно связано с равенством?

Почему это так? Что такого сложного в том, чтобы сделать оператор равенства по умолчанию чем-то более сильным? Поэтому вместо того, чтобы просто сравнивать ссылки, почему так сложно сравнивать структурные свойства?

Я знаю, что многие языки предоставляют средства для перегрузки определенных операторов, чтобы означать что-то еще, так что == будет означать то, что вы хотите, чтобы оно означало вместо обычного слабого ссылочного равенства. Мой вопрос заключается не в том, что язык предоставляет такие возможности, а в том, почему оператор равенства по умолчанию не является чем-то более разумным, так что [1,2,3] == [1,2,3] оценивает значение true по умолчанию и не требует вмешательства программиста.

В питона в приведенном выше примере имеет значение верно, но если вы определяете следующий класс

class A: 
    def __init__(self, prop): 
    self.prop = prop 

, а затем сравнить a = A(1) с b = A(1), то ответ будет ложным, хотя структурно a и b одинаковы и есть нет способа рассказать им обособленно, если все, что вы знаете, это бит-шаблон, который определяет объект.

+0

Почему предположение, что это трудно сделать только потому, что они решили реализовать его так, как они это сделали? – kinakuta

+0

@kinakuta, потому что почти каждый язык там делает это так, что указывает на какой-то барьер. Если бы было легко, кто-то там бы реализовал язык, который делает очевидную вещь для равенства массива и более общих типов. – davidk01

ответ

2

Не все языки работают так, как вы описываете. Например, в Python == равенство и is является ссылка сравнения:

>>> a = [1,2,3] 
>>> b = [1,2,3] 
>>> a == b 
True 
>>> a is b 
False 
+0

Это верно, но если я определяю свой собственный пользовательский класс со своими собственными свойствами, тогда 'a = Klass (val)' не будет равен 'b = Klass (val)'. – davidk01

+0

@ davidk01: Вам необходимо реализовать метод ['__eq__'] (http://docs.python.org/reference/datamodel.html#object.__eq__) для вашего класса. Это то, что вызывается '=='. –

+0

Да. Это моя точка зрения. Что так тяжело в том, что оператор '__eq__' по умолчанию работает правильно. – davidk01

2

Не все языки делают это. C++ использует == для объектов для обозначения равенства (хотя == на указателях означает ссылочное равенство). Я считаю (хотя я не совсем уверен), что язык программирования D содержит == для равенства значений и оператора is для ссылочного равенства.

Я думаю, что это всего лишь дизайнерское решение для JavaScript и несколько других языков. Нет причин, чтобы это было так.

+0

Итак, в D '[1,2,3] == [1,2,3]' оценивается как true? – davidk01

0

почти каждый язык реализует равенство как равенство ссылок

Как указано types метки на этот вопрос, многие Языки реализуют равенство как поведение типа. Это имеет смысл: большинство типов будут иметь некоторые свойства, которые могут меняться в экземпляре без изменения семантического значения этого экземпляра.

Итак, ответ, который я бы дал, равен: равенство не сложно, это зависит от типа, чтобы определить, какие экземпляры равны. Любые невыполнения обязательств в отсутствие такого явного решения должны быть консервативными.

Если вы создаете нестандартный тип, это заставляет вас принять решение; если язык поддерживает наследование, используйте это, чтобы выразить свое решение о том, что «равенство должно вести себя как этот другой более простой тип». В противном случае запрограммируйте тест равенства явно для типа, как это делается для существующих типов, которые, как вы полагаете, имеют правильное поведение.

Смежные вопросы