2016-03-01 4 views
0

Я пытаюсь создать обертку вокруг данных, сохраненных в базе данных redis. Я хочу сделать доступ к нему как можно более нормальным, как если бы у меня значение scala какого-то типа. Работает, за исключением сравнения с чем-либо (с == или аналогичным).
Так что я хочу иметь возможность сравнить его с объектами внутреннего типа.Сравнение объекта-обертки универсального типа со всем, что сопоставимо с внутренним типом?

Лучшее сначала приведу пример кода. Это грубая абстракция моей обертки:

case class RedisObjectValue[T](name: String, default: T) { 
    def :=(value: T): Boolean = { 
    redisMagic.set(name, value) 
    } 

    def get: T = { 
    redisMagic.get[T](name).getOrElse(default) 
    } 

    override def equals(o: Any) = o match { 
    case ov: RedisObjectValue[T] => 
     if (this.hashCode() == ov.hashCode()) true // Same reference 
     else this.get == ov.get 
    case v => 
     // If we don't compare to another RedisObjectValue, let the equals method of data type handle it 
     this.get.equals(v) 
    } 
} 

У меня есть неявное преобразование, установленное в объекте компаньона, так что я могу использовать оболочку, где я хотел бы использовать базовый тип.

object RedisObjectValue { 
    implicit def objectValueToValue[T](ov: RedisObjectValue[T]): T = { 
    ov.get 
    } 
} 

Итак, как я уже сказал, все работает.
Кроме сравнения материала. Для этого предположим, что у меня есть класс Player два значения, userId и name.

class Player { 
    val userId = RedisObjectValue("userId", 0) 
    val name = RedisObjectValue("player", "Unknown") 
} 

И теперь у меня есть список игроков и вы хотите отфильтровать, чтобы получить всех игроков с именем «Неизвестно».

list.filter(_.name == "Unknown") 

Какой из них не работает. Если я продюмлю фильтр-фильтр и напишу функцию, он скажет мне в IntelliJ «Сравнение несвязанных типов».
И да, я понимаю, что это говорит мне, но я хочу это решить. Я имею в виду, что я могу легко сравнить Long to Int и подобные вещи, поэтому должен быть способ сделать их сопоставимыми, не так ли?

В приведенном выше коде я даже написал функцию равенства, которая использует сравнение с внутренним типом, но кажется, что он не используется.

Конечно, я всегда могу позвонить .get о значениях, например players.filter(_.name.get == "Unknown"), но это немного грязно, и я бы хотел этого избежать.

EDIT: Нашел реальную проблему после некоторого анализа

Старого текста еще выше для чтения, я объясню проблему здесь и сейчас.
У меня есть фрагмент кода, который показывает, что не работает: https://ideone.com/AmQrkH

проблемы: RedisObjectValue определяется как Long. Когда я сравниваю сейчас с

players.filter(_.userId == 2) 

, например, он не дает никаких результатов, даже если есть игроки с userId 2, или быть более точным: 2l.

Для прямого Long это не проблема.

players.filter(_._id == 2) 

работает.
Так ли какое-либо исправление для этого, так что сопоставимые экземпляры классов до T также можно сравнить с RedisObjectValue[T], а не только T?

+0

Что именно вы имеете в виду, когда вы говорите «это не работает»? Похоже, что вы должны работать. Показать полный (минимальный) фрагмент кода, который воспроизводит проблему. – Dima

+0

Я объяснил ошибку, о которой говорит IntelliJ. И «это не работает, означает, что ни один из элементов в списке не соответствует критериям, даже если они есть где-то. Проблема заключается в том, что компилятор видит сравнение между экземпляром« RedisObjectValue [T] »и экземпляром типа 'T', который не соответствует типам, поэтому обычно не сопоставим. Я попытаюсь закодировать рабочий фрагмент. – Wolfsblvt

+0

Это работает для меня: https://gist.github.com/anonymous/b659523c8a5897f64d4b Итак, должен быть какой-то нюанс в коде, который вы не показывали, что вводит проблему. Вот почему я просил полный фрагмент кода для воспроизведения. – Dima

ответ

1

Заменить this.get.equals(v) на get == v. (Удаление не связано, просто хорошая идея в целом, главное, чтобы использовать == вместо equals).

Рассмотрим это:

scala> 2 equals 2L 
res79: Boolean = false 

scala> 2 == 2L 
res80: Boolean = true 
+0

Хорошо, это, кажется, ответ здесь. Теперь это работает для меня. Это довольно запутанно, я думал, что '. ==' просто вызывает '.equals' внутренне, потому что мне нужно было сопоставить свой объект с реализацией функции equals? – Wolfsblvt

+1

Да ... Я на самом деле не уверен, что такое объяснение. На самом деле это просто вызов '.equals', но есть еще одна магия, которая происходит с бокс и unboxing примитивными типами. – Dima

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

  • Нет связанных вопросов^_^