Опрос: Правильное ли поведение равенства, когда переданный объект не соответствует типу LHS? - PullRequest
4 голосов
/ 13 декабря 2008

Я задал связанный вопрос о findbugs, но давайте зададим более общий вопрос.

Предположим, что я работаю с объектно-ориентированным языком, в котором возможен полиморфизм.

Предположим, что язык поддерживает статическую проверку типов (например, Java, C ++)

Предположим, что язык не допускает отклонения в параметрах (например, Java, снова ...)

Если я переопределяю операцию равенства, которая принимает Object в качестве параметра, что мне следует делать в ситуации, когда параметр не имеет тот же тип или подтип, что и LHS, к которому был обращен эквивалентный вызов?

Вариант 1 - вернуть false, поскольку объекты явно не равны

Вариант 2 - генерировать исключение приведения, потому что если бы язык действительно поддерживал дисперсию (что было бы предпочтительнее), это было бы воспринято во время компиляции как ошибка; таким образом, обнаружение этой ошибки во время выполнения имеет смысл, поскольку ситуация, когда отправляется другой тип, должна быть недопустимой.

Ответы [ 5 ]

3 голосов
/ 13 декабря 2008

Я голосую за вариант 1. Возможно, что два объекта разных типов будут равны - например, int и double, если объекты первого класса, могут быть корректно приведены друг к другу и сопоставимы математически. Кроме того, вы можете рассматривать различные подклассы как равные в некоторых отношениях, но ни один из них не может быть приведен к другому (хотя они могут быть получены из одного и того же родителя).

1 голос
/ 13 декабря 2008

Вернуть false, потому что объекты не равны.

Я не понимаю, как бросить ClassCastException было бы лучше здесь.

Существуют контракты в интерфейсах, таких как Collection или List, которые фактически зависят от того, может ли любой объект проверить на равенство с любым другим объектом.

0 голосов
/ 13 декабря 2008

Dr. Java Q & A Доббса говорит, что лучшая практика заключается в том, что оба они одного типа. Поэтому я голосую за вариант 1.

0 голосов
/ 13 декабря 2008

Хммм .. Мне также нравится Вариант 1 по следующим 4 причинам:

1) Объекты, по-видимому, не были равны, какими бы условиями вы не проверяли

2) Бросок ClassCastException требует проверки этого исключения каждый раз, когда вы проводите сравнение, и я думаю, что это делает код менее понятным или, по крайней мере, более длинным ...

3) Исключение приведения класса является лишь симптомом проблемы, заключающейся в том, что два объекта не были равны даже на уровне типа.

4) Как пользователь "cbo" упоминал выше, double / int равны, несмотря на то, что их типы различны (4.0 == 4), и это также относится к другим типам.

Отказ от ответственности: я могу позволить своим путям Python раскрасить дебаты по Java:)

0 голосов
/ 13 декабря 2008

Это зависит.

SomeClass obj1 = new SomeClass();
object other = (object)obj1;

return obj1.Equals(other); // should return "true", since they are really the same reference.

SomeClass obj1 = new SomeClass();
object other = new object();

return obj1.Equals(other); // should return "false", because they're different reference objects.

class SomeClass { }
class OtherClass { }

SomeClass obj1 = new SomeClass();
OtherClass obj2 = new OtherClass();

return obj1.Equals(obj2); // should return "false", because they're different reference objects.

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

Вы не должны вызывать исключение любого типа, потому что вы принимаете базовый класс объекта в качестве параметра.

...