Вынудите класс переопределить .equals метод

s = a + p
b >= s && a != 1 && b - s - 1 > 0

Проверено, возвращает то же логическое значение, что и вопрос.

Программа, которую я использовал для проверки: (весело писал ее)

#include <iostream>
using namespace std;

typedef unsigned int uint;

bool condition(uint a, uint b, uint p)
{
        uint s = a + p;
        return uint(    b >= s && a != 1 && b - s - 1 > 0    )
        == uint(    (((a+p) <= b) && (a == 0 || a > 1) && (b >= p))
                 && ((b - (a + p) == 0) || (b - (a + p) > 1))    );
}

void main()
{
    uint i = 0;
    uint j = 0;
    uint k = 0;

    const uint max = 50;

    for (uint i = 0; i <= max; ++i)
        for (uint j = 0; j <= max; ++j)
            for (uint k = 0; k <= max; ++k)
                if (condition(i, j, k) == false)
                {
                    cout << "Fails on a = " << i << ", b = " << j;
                    cout << ", p = " << k << endl;

                    int wait = 0;
                    cin >> wait;
                }
}
51
задан Tom Neyland 22 October 2009 в 23:35
поделиться

11 ответов

Нет, нельзя. Однако вы можете использовать абстрактный базовый класс вместо интерфейса и сделать equals () abstract:

abstract class Command {
   // put other methods from Command interface here

   public abstract boolean equals(Object other);
   public abstract int hashCode();
}

Подклассы Command должны затем предоставить свои собственные методы equals и hashCode.

Обычно плохая практика заставлять пользователей API расширять базовый класс, но в данном случае это может быть оправдано. Кроме того, если вы сделаете Command абстрактным базовым классом вместо интерфейса, вместо того, чтобы вводить искусственный базовый класс в дополнение к командному интерфейсу, тогда нет риска, что пользователи вашего API это неправильно.

83
ответ дан 7 November 2019 в 10:03
поделиться

Вот вариант некоторых других предлагаемых решений:

public abstract class CommandOverridingEquals implements Command {
    public abstract boolean equals(Object other);
    public abstract int hashcode();
}

Map<String, CommandOverridingEquals> map = 
    new HashMap<String, CommandOverridingEquals>();

Или, если вы действительно хотите быть уверенным, используйте проверенную хэш-карту; например

Map<String, CommandOverridingEquals> map = Collections.checkedMap(
    new HashMap<String, Command>(),
    String.class, CommandOverridingEquals.class);

Но что бы вы ни делали, вы не можете остановить кого-то, делая это:

public class AntiFascistCommand extends CommandOverridingEquals {
    public boolean equals(Object other) { return super.equals(other); }
    public int hashcode() { return super.hashcode(); }
    ...
}

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

ИМО, это плохая идея - пытаться принудить разработчика к определенному шаблону реализации. Было бы лучше поместить несколько строгих предупреждений в Javadocs и положиться на разработчиков , которые сделают правильный выбор .

0
ответ дан 7 November 2019 в 10:03
поделиться

Поскольку equals (), унаследован от Object I сомневаюсь, что вы не можете добиться этого, поскольку для каждого типа существует автоматическая унаследованная реализация equals () .

0
ответ дан 7 November 2019 в 10:03
поделиться

Как уже объяснялось в других ответах, нет, вы не можете форсировать то, что вы пытаетесь сделать.

Одна вещь, которая может работать «достаточно», - это определить второй интерфейс, назовите это MappableCommand.

public interface MappableCommand 
{

}

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

Затем вы можете установить для типа Value вашей карты значение MappableCommand, и только MappableCommands можно будет добавить на карту.

Это похоже на логику, по которой нужно реализовать (пустой) интерфейс Serializable для классов, которые могут быть сериализованы с помощью механизмов сериализации по умолчанию Java.

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

Fake Edit:

Если вы хотите сделать это требование более очевидным, вы можете определить новый интерфейс следующим образом

public interface MappableCommand 
{

    public void iOverrodeTheEqualsMethod();

    public void seriouslyIPromiseThatIOverrodeIt();

}
0
ответ дан 7 November 2019 в 10:03
поделиться

Вы можете создать логическое myEquals () в интерфейсной команде и создать адаптер следующим образом:

class MyAdapter{
  Command c;
  boolean equals(Object x) {
    return c.myEquals((Command)x);
  }
}

Затем вы просто используете карту .put (key, new MyAdapter (command)) вместо map.put (key, command)

1
ответ дан 7 November 2019 в 10:03
поделиться

Я не думаю, что возможно принудительное переопределение равных значений, поскольку оно исходит из класса Object.

В соответствующем примечании обратите внимание, что вам нужно переопределить метод 'hashCode' из класс Object, когда вы переопределяете equals. Это становится особенно важным, если вы собираетесь использовать экземпляры своих классов в качестве ключей карты. Проверьте эту статью: http://www.artima.com/lejava/articles/equality.html который дает некоторые подсказки о том, как правильно переопределить равные

0
ответ дан 7 November 2019 в 10:03
поделиться
interface A{
    public boolean equal2(Object obj);
}

abstract class B implements A {

    @Override
    public boolean equals(Object obj) {
        return equal2(obj);
    }

}


class C extends B {

    public boolean equal2(Object obj) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
1
ответ дан 7 November 2019 в 10:03
поделиться

Это было бы возможно, только если бы Command была интерфейсом или абстрактным классом, где equals (..) - это метод объявлен как абстрактный.

Проблема в том, что Object, который является суперклассом всех объектов, уже определяет этот метод.

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

Попытайтесь обойти это, имея специальный метод API, например CommandEquals.

1
ответ дан 7 November 2019 в 10:03
поделиться

Можете ли вы расширить свои объекты из абстрактного XObject, а не из java. lang.Object?

public abstract class XObject
 extends Object
{
@Override
public abstract boolean equals(Object o);
}
17
ответ дан 7 November 2019 в 10:03
поделиться

Хорошо, если вам нужна среда выполнения проверьте, что вы можете сделать что-то вроде:

    interface Foo{

}
class A implements Foo {

}
class B implements Foo {
    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }
}

public static void main(String[] args) {
    Class<A> clazzA = A.class;
    Class<B> clazzB = B.class;

    Class<Object> objectClass = Object.class;
    try {
        Method methodFromObject = objectClass.getMethod("equals",Object.class);
        Method methodFromA = clazzA.getMethod("equals",Object.class);
        Method methodFromB = clazzB.getMethod("equals",Object.class);
        System.out.println("Object == A" + methodFromObject.equals(methodFromA));
        System.out.println("Object == B" + methodFromObject.equals(methodFromB));
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
}

Выведет true для первого и false для второго. Если вы хотите, чтобы время компиляции выглядело так, как будто единственный вариант - создать аннотацию и использовать инструмент обработки аннотаций, чтобы проверить, что все аннотированные классы переопределяют равны.

1
ответ дан 7 November 2019 в 10:03
поделиться

Можно ли предоставить свой собственный java.util.comparator для рассматриваемой карты?

0
ответ дан 7 November 2019 в 10:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: