Я пытаюсь создать обертку вокруг данных, сохраненных в базе данных 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
?
Что именно вы имеете в виду, когда вы говорите «это не работает»? Похоже, что вы должны работать. Показать полный (минимальный) фрагмент кода, который воспроизводит проблему. – Dima
Я объяснил ошибку, о которой говорит IntelliJ. И «это не работает, означает, что ни один из элементов в списке не соответствует критериям, даже если они есть где-то. Проблема заключается в том, что компилятор видит сравнение между экземпляром« RedisObjectValue [T] »и экземпляром типа 'T', который не соответствует типам, поэтому обычно не сопоставим. Я попытаюсь закодировать рабочий фрагмент. – Wolfsblvt
Это работает для меня: https://gist.github.com/anonymous/b659523c8a5897f64d4b Итак, должен быть какой-то нюанс в коде, который вы не показывали, что вводит проблему. Вот почему я просил полный фрагмент кода для воспроизведения. – Dima