2015-08-19 9 views
1

У меня есть случай, когдаMap.contains с супер-типа ключа типа

trait EventLike 
trait Event extends EventLike 

trait API { 
    private var map = Map.empty[Event, Any] 

    def contains(e: EventLike): Boolean = map.contains(e) 
} 

Это не работает из-за инвариантности в ключевых типу карты:

<console>:58: error: type mismatch; 
found : EventLike 
required: Event 
      def contains(e: EventLike): Boolean = map.contains(e) 
                   ^

Что хорошая работа с минимальным штрафом за производительность. То есть, я специально не хочу, чтобы ввести эту ужасную вещь:

def contains(e: EventLike): Boolean = e match { 
    case e1: Event => map.contains(e1) 
    case _ => false 
    } 

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

+0

Почему бы вам не добавить более конкретный содержащий метод API для событий? –

+0

@SeanVieira, потому что сайт вызова обычно имеет дело с непрозрачными объектами EventLike. –

ответ

2

Вы можете объявить карту в Map[EventLike, Any]:

trait API { 
    private var map = Map.empty[EventLike, Any] 
    def contains(e: EventLike): Boolean = map.contains(e) 

    def add(e:Event): Unit = { 
    map += (e -> ???) 
    } 
} 

Вы все еще можете заполнить карту только с Event ключами, при поиске как Event и EventLike.

UPD

Если вы не возражаете против использования Java изменяемых коллекций, вы можете использовать HashMap, который принимает любой объект в качестве аргумента того, содержит независимо от параметров типа карты:

trait API { 
    private val map = new java.util.HashMap[Event, Any] 
    def contains(e: EventLike): Boolean = map.containsKey(e) 
} 
+0

К сожалению, это просто перемещает совпадение шаблона до точки, где я хочу получить« Событие » экземпляры с карты ... –

+0

@ 0__ вы не указали, что вам нужно получить ключи вашей карты в качестве «события» в вашем вопросе. – Aivean

+0

@ 0__ проверьте обновление. – Aivean

0

EventLike является супертипом Event, поэтому это не сработает, даже если тип ключа Map был ковариантным.

Вы в основном хотите проверить EventLike является Event, и вы можете сделать это только во время выполнения, либо с раствором или с чем-то вроде

def contains(e: EventLike): Boolean = 
    e.isInstanceOf[Event] && map.contains(e.asInstanceOf[Event] 

Будет не статическая проверка типов работы в вашем случае ?

def contains(e: Event): Boolean = map.contains(e) 
+1

Обратите внимание, что перегрузка неверна, поскольку метод разрешен во время компиляции, а не отправляется на основе типа времени выполнения. Вы можете проверить это с помощью: val e: EventLike = new Event {} ' –

+0

@ 0__, вы правы, я убираю эту часть –

Смежные вопросы