문제

공통 인터페이스를 구현하는 클래스가 많이 있습니다.명령.

그리고 이 클래스는 Map으로 이동합니다.

지도가 올바르게 작동하려면 Command를 구현하는 각 클래스에서 Object.equals(Object other) 방법.

괜찮아.

하지만 나는 동등함을 강제로 무시하고 싶습니다.=> 명령을 재정의하지 않는 항목이 같음을 구현하면 컴파일 오류가 발생합니다.

그게 가능해요?

편집하다 :그런데, 해시코드 재정의도 강제로 적용해야 합니다...

도움이 되었습니까?

해결책

아니, 당신은 할 수 없습니다. 그러나 할 수있는 일은 인터페이스 대신 추상적 인 기본 클래스를 사용하고 equals() 요약:

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

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

서브 클래스 Command ~ 해야 하다 그런 다음 자신의 평등 및 해시 코드 방법을 제공하십시오.

API 사용자가 기본 클래스를 연장하도록 강요하는 것은 일반적으로 나쁜 관행이지만이 경우 정당화 될 수 있습니다. 또한, 당신이 만든 경우 Command 인공 기본 클래스를 소개하는 대신 인터페이스 대신 추상적 인 기본 클래스 덧셈 명령 인터페이스에는 API 사용자가 잘못 될 위험이 없습니다.

다른 팁

java.lang.object 대신 추상적 인 xobject에서 객체를 확장 할 수 있습니까?

public abstract class XObject
 extends Object
{
@Override
public abstract boolean equals(Object o);
}

아버지가 이미 평등과 해시 코드 방법을 과대 평가 한 후 다시 문제가 있기 때문에 손자가 있으면 초록 수업이 작동하지 않습니다.

Annotatins와 Apt를 사용해보십시오 (http://docs.oracle.com/javase/1.5.0/docs/guide/apt/gettingstarted.html) 끝내기 위해.

이는 Command가 인터페이스이거나 추상 클래스인 경우에만 가능합니다. 여기서 equals(..)는 추상으로 선언된 메서드입니다.

문제는 모든 객체의 슈퍼클래스인 Object가 이미 이 메소드를 정의하고 있다는 점이다.

런타임 시 이것이 문제임을 나타내려면 예외를 발생시켜 API 사용자가 강제로 이를 무시하도록 할 수 있습니다.그러나 적어도 내가 아는 한 컴파일 타임에는 불가능합니다.

API별 메서드를 사용하여 문제를 해결해 보세요.CommandEquals.다른 옵션은 (언급한 대로) Equals 추상 메서드를 정의하는 다른 클래스를 확장하는 것입니다.

당신은 만들 수 있습니다 boolean myEquals() 안에 interface Command, 다음과 같이 어댑터를 만듭니다.

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

그럼 당신은 그냥 사용합니다 map.put(key, new MyAdapter(command)) 대신에 map.put(key, command)

런타임 확인을 원한다면 다음과 같은 작업을 수행 할 수 있습니다.

    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를 인쇄합니다. 컴파일 시간을 원한다면 시간이 유일한 옵션은 주석을 만들고 주석 처리 도구를 사용하여 모든 주석이 붙은 클래스가 동등한 지 확인하는 것입니다.

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.");
    }
}

부터 equals() 상속됩니다 Object 나는 당신이 정말로 그것을 강요 할 수 없다는 것을 의심합니다. 모든 타입 자동 상속 구현이 있습니다 equals() 사용 가능.

나는 객체 클래스에서 나오는 것처럼 평등을 강요하는 것이 불가능하다고 생각하지 않습니다.

관련 메모에서, 당신은 equals를 재정의 할 때 객체 클래스에서 '해시 코드'메소드를 무시해야한다는 점에 유의하십시오. 클래스의 인스턴스를지도의 열쇠로 사용하려면 이는 매우 중요해집니다. 이 기사를 확인하십시오 :http://www.artima.com/lejava/articles/equality.html올바른 방식으로 동등한 방법에 대한 힌트를 제공합니다.

다른 답변에서 이미 설명했듯이, 당신이 시도하는 것을 강요할 수는 없습니다.

'충분히' 작동할 수 있는 한 가지 방법은 두 번째 인터페이스를 정의하는 것입니다. 이를 MappableCommand라고 합니다.

public interface MappableCommand 
{

}

이 인터페이스에 대한 문서에서는 클래스 디자이너가 귀하가 명시한 요구 사항을 고려한 경우에만 클래스가 이(빈) 인터페이스를 구현해야 한다고 명시합니다.

그런 다음 지도의 값 유형을 MappableCommand로 설정하면 MappableCommand만 지도에 추가할 수 있습니다.

이는 Java의 기본 직렬화 메커니즘에 의해 직렬화될 수 있는 클래스에 대해 (빈) 직렬화 가능 인터페이스를 구현해야 하는 이유 뒤에 있는 논리와 유사합니다.

이것이 작동하지 않으면 런타임 오류가 발생하는 것에 만족해야 할 수도 있습니다.

가짜 편집:

이 요구 사항을 더 명확하게 만들고 싶다면 다음과 같이 새 인터페이스를 정의할 수 있습니다.

public interface MappableCommand 
{

    public void iOverrodeTheEqualsMethod();

    public void seriouslyIPromiseThatIOverrodeIt();

}

다음은 다른 제안 된 솔루션의 변형입니다.

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(); }
    ...
}

나는 이런 종류의 일이 트랙에서 문제를 일으킬 것이라고 생각하는 경향이 있습니다. 예를 들어, 다른 기본 클래스를 확장하고 (우연히) 재정의하는 기존 명령 클래스가 있다고 가정합니다. equals 그리고 hashcode 규정 된 방식으로. 문제는 그 수업을 사용할 수 없다는 것입니다. 대신, 나는 그들을 상환하거나 많은 포장지를 써야합니다.

IMO, 개발자를 특정 구현 패턴으로 강제하려고 시도하는 것은 나쁜 생각입니다. Javadocs에 강한 경고를하고 개발자에게 의지하는 것이 더 낫습니다. 옳은 일을하십시오.

자신의 것을 제공 할 수 있습니까? java.util.comparator 문제의지도에?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top