Pozbycie się kowariancji jest oczywiście nieuzasadnione i nie jest dozwolone. Biorąc pod uwagę m: Map[A, String]
i v : Any
, możesz wykonać val mm : Map[A, Any] = m + v
. Tak mówi definicja, a wszyscy operatorzy muszą za nią podążać. Twoja klasa może być niezmienna, ale musi implementować pełny interfejs kowariancyjny Map.
Teraz redefinicja +
, aby rzucić błąd, to inna historia (jeszcze niezbyt dźwiękowa). Problem z nową metodą +
polega na tym, że po usunięciu generics ma ona tę samą sygnaturę, co inna metoda +
. Istnieje pewna sztuczka: dodaj niejawny parametr, aby mieć dwa parametry w podpisie, co odróżnia go od pierwszego.
def +(kv : (A,B))(implicit useless: A <:< A) : MyMap[A,B]
(to naprawdę nie ma znaczenia, co ukryte parametr szukasz, tak długo, jak jeden został znaleziony. implicit useless: Ordering[String]
działa tak samo dobrze)
Doing że masz zwykły problem z przeciążeniem . Jeśli dodasz B bez kompilatora wiedząc, że tak jest, zostanie wywołana metoda błędu. Lepiej byłoby wykonać tam test typu, aby instancje B były akceptowane niezależnie od tego. To wymagałoby otrzymania Manifestu [B] na twojej mapie.
Może chcesz użyć mapy elementu zamiast wyprowadzać? – Owen
Ponadto, dlaczego musi być niezmienna? Pomyślałem (nie znam zbyt wiele Scali), że jedyną potrzebą niezmienności jest to, czy może to być źródło, czy zlew, ale mapy są niezmienne, więc nie może to być zlew. – Owen
Chcę zaimplementować mapę dwukierunkową. Nic wielkiego, jeśli zaimplementuję Mapę i po prostu przekazuję obie mapy wewnętrzne, które definiują mapowanie do przodu i do tyłu, ale w tym przypadku potrzebuję niezmienności. –