2017-10-05 1 views
0

이 우리의 응용 프로그램에서 무슨 일이 일어나고 있는지의 단순화 된 코드입니다 .String은 java.lang.Boolean으로 캐스팅 될 수 없습니다.클래스 캐스트 예외 ("=="재정의)

나는 잘못된 것을하고 있지만 무엇을 이해하지 못한다는 것을 알고 있습니다.

편집

나는 변경하여 코드를 수정했습니다 :

class First { def ==(first:First)= true} 

을 지금 REPL의 오류는 다음과 같습니다

error: type mismatch; 
found : First(in object $iw) 
required: First(in object $iw) 
     Second(new First) == Second(new First) 

더욱 예상치 못한 나에게 :

\

업데이트 두 번째 예제는 내 잘못입니다. REPL에서 클래스 First를 대화식으로 변경하여 이상한 결과를 초래했습니다. 처음부터 시작 그것은 작동합니다. 여전히 첫 번째 ...

답변

1

Second이 경우 클래스이며 사용자 정의 equals 방법을 정의하거나 상속하지 않기 때문에, Second#equals에 대해 생성 된 코드는 ==(First) 아닌 것

override def equals(x: Any): Boolean = x match { 
    case x: Second => first == x.first 
    case _ => false 
} 

첫 번째 지점의 ==과 같아야합니다 평범한 ==(Any), 왜냐하면 그것은 더 특정한 오버로드이기 때문입니다. 따라서 "Second"을 선언 할 때 컴파일 오류가 발생합니다.

그러나 스택 추적에서 컴파일러가 어딘가에 대신 (x match ...).asInstanceOf[Boolean] 또는 (first == x.first).asInstanceOf[Boolean] 중 하나를 삽입하는 것으로 보입니다. 솔직하게 말해서, 나는 이것이 왜 이렇게 쓰여질 지 이유를 정말로 생각할 수 없다. 그러나 이로 인해 Second 컴파일하고 나중에 호출이 실패합니다.

+1

이 설명은 물을 보유하지 않는 것처럼 보입니다. 컴파일러는 실제로 오버로드 된 메서드를 호출 할 때 반환 형식을 고려할 정도로 똑똑합니다. 이렇게하면 :'class Foo {def bar (x : Any) : Boolean = false; bar foo : Boolean = new Foo(). bar ("baz")는 제대로 작동하고'false'를 반환합니다. – Dima

+0

@Dima 이상하게도, http://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#overloading-resolution을 올바르게 읽는다면 제대로 작동하지 않을 것입니다 : 둘 다 대안이 적용 가능하며 (매개 변수 유형에만 의존 함), 리턴 유형은 다형성 유형에 대해서만 중요합니다. 물론 규칙이 매우 복잡하기 때문에 뭔가 빠져있을 수 있습니다. –

+0

@Dima 또한 컴파일러가 캐스트를 삽입하기 때문에 ('ClassCastException'이 없기 때문에) 캐스트를 삽입하기 때문에'first == x.first' 자체에 예상되는 유형이 없으므로 컴파일러는 그것을 사용하여 과부하를 선택할 수 없습니다. 즉, 내 설명에 따르면 당신은'val foo : Boolean = new Foo(). bar ("baz"). asInstanceOf [Boolean]'대신에 시도 할 필요가있다. –

2

== 연산자를 재정의하지 마십시오.이 연산자는 scala 컴파일러에서 Java의 Object.equals 메소드와 비슷한 의미로 제공됩니다. 이것이 항상 부울을 반환하는 이유입니다. 그래서 당신이 자신의 연산자를 구현할 때 scala가 결과를 부울로 캐스팅하려한다고 가정합니다.

+0

나는 당신의 대답을 이해하지만 여전히 나는 예기치 않은 결과를 느낀다. 실제 사례에서는 이미 다른 접근 방식을 사용하여 해결했지만 여전히이 예외는 나를 놀라게합니다. 덕분에 – maborg

+0

나는 그것을 더 잘 이해하기 위해 repl로 인라인을 테스트하고 있지만 여전히 약간의 버프가있다. :) – maborg

3

업데이트 된 버전 (부울을 반환하는 ==)이 유용합니다.

이상한 오류의 원인은 REPL에서 시도한 것이므로 First 클래스를 다시 정의했지만 Second은 다시 정의하지 않았기 때문일 수 있습니다.

REPL은 스칼라에서는 일반적으로 불가능한 클래스와 변수를 다시 정의 할 수있는 몇 가지 속임수를 사용하므로 기본적으로 First이라는 두 가지 버전이 있고 결국 Second 정의는 여전히 이전 버전을 참조하지만 사용자가 보내는 버전 new First()으로 생성자에 새로운 것은 - 따라서 불일치입니다.

Second 클래스를 다시 정의하면 다시 작동합니다.

== BTW를 다시 정의하는 데 많은 잘못은 없지만 같은 경우 효과가있는 경우 equals을 재정의하는 것이 더 일반적입니다. ==의 기본 구현은 equals을 호출하기 때문에 하나의 문제는 하위 사용자가 서브 클래스 중 하나에서 equals을 무시하고 예상 한대로 처리하지 못한다는 것입니다.

+0

예, 문제는 REPL에서 대화 형으로 변경하는 것으로 인해 발생했습니다. 처음부터 시작하여 작동합니다. thnks – maborg

+0

== 대신에 equals를 오버라이드하지만, == call이 왜 내 예제가 실패하는 지와 같으면? – maborg

+0

예를 들어, 문자열을 반환하기 위해 재정의했기 때문에 오류가 발생합니다. 부울 – Dima

관련 문제