2011-08-17 1 views
6

스칼라의 불변의 맵에서 파생시키고 싶습니다.스칼라에서 기본 클래스/특성의 분산을 변경할 수 있습니까?

trait Map[A, +B] 

불행하게도, 내 구현 내가 다음을 시도 B.에서 일정 할 필요가 있지만, 성공하지 : 같은 정의

def +(kv : (A, B)) : MyMap[A, B] = { ... } 

override def +[B1 >: B](kv : (A, B1)) : MyMap[A, B1] = 
    throw new IllegalArgumentException() 

아마 @uncheckedVariance과 트릭이있다?

+1

아마 도출 대신 회원지도를 사용할 수 있습니까? – Owen

+0

또한 왜 불변 할 필요가 있습니까? 나는 (비록 스칼라는 많이 알지 못한다) 당신이 불변성을 필요로하는 유일한 시간은 소스와 싱크가 될 수 있지만, 맵은 불변이므로 싱크가 될 수 없다는 것이다. – Owen

+0

양방향지도를 구현하고 싶습니다. Map을 구현하고 정방향 및 역방향 매핑을 정의하는 두 개의 내부 맵에 위임하면 큰 문제는 아니지만이 경우에는 불변성이 필요합니다. –

답변

1

물론 공분산을 제거하는 것은 당연히 불건전이며 허용되지 않습니다. m: Map[A, String]v : Any을 입력하면 val mm : Map[A, Any] = m + v을 사용할 수 있습니다. 이것은 Map 정의가 말하는 것이며 모든 구현자가 따라야합니다. 클래스는 불변이지만지도의 전체 공변 인터페이스를 구현해야합니다.

이제 오류를 던지기 위해 +을 다시 정의하는 것은 다른 이야기입니다 (별로 소리는 아닙니다). 새로운 + 메서드의 문제점은 제네릭 삭제 이후에 다른 + 메서드와 동일한 서명이 있다는 것입니다. 속임수 : 암시 적 매개 변수를 추가하여 서명에 두 개의 매개 변수가 있으므로 첫 번째 매개 변수와 다릅니다.

def +(kv : (A,B))(implicit useless: A <:< A) : MyMap[A,B] 

(이것은 정말 문제와 마찬가지로 잘 작동 암시 당신이 한 일이 발견으로, 찾고있는 매개 변수입니다. implicit useless: Ordering[String] 않습니다), 당신은 오버로드와 일반적인 문제를

그 일이 . 컴파일러없이 B를 추가하면 실패한 메소드가 호출됩니다. B 인스턴스가 무엇이든 허용되도록 유형 검사를 수행하는 것이 더 나을 수도 있습니다. 그러면지도에 Manifest [B]가 있어야합니다.

3

불변의 맵에서 불변 버젼을 파생하면 타입 안정성이 깨질 수 있습니다. 예를 들어 : Map이 공변 때문에

val dm = DiotMap(1 -> "abc") 
val m: Map[Int, Any] = dm 

이 선언은 유효합니다. 컬렉션에서 공분산을 처리 할 수없는 경우 m을 사용하면 어떻게됩니까?