I am trying to build a wrapper around data saved in a redis database.
What I want to do is access it as normal as possible as if I have a scala value of some type.
It works, except for comparing it to anything (with ==
or similar).
So I want to be able to compare it to objects of the inner type.
Best I'll give example code first. This is a rough abstraction of my wrapper:
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)
}
}
I have an implicit conversion set up in the companion object so that I can use the wrapper wherever I would use the base type.
object RedisObjectValue {
implicit def objectValueToValue[T](ov: RedisObjectValue[T]): T = {
ov.get
}
}
So, as I said, everything works.
Except the comparing stuff. For that, let's say I have a class Player
two values, userId
and name
.
class Player {
val userId = RedisObjectValue("userId", 0)
val name = RedisObjectValue("player", "Unknown")
}
And now I have a list of players and want to filter to get all players with name "Unknown".
list.filter(_.name == "Unknown")
Which does not work. If I extend the filter filter call and write a function, it tells me in IntelliJ "Comparing unrelated types".
And yeah, I understand what it is telling me, but I want to solve that. I mean I can easily compare Long to Int and similar stuff, so there must be a way to make them comparable, right?
In the code above I have even written the equals function which uses the comparison to the inner type, but it seems like it is not used.
Of course, I can always call .get
on the values, like players.filter(_.name.get == "Unknown")
, but that's a bit dirty and I would love to avoid that.
Old text still above for reading, I will explain the problem here now.
I have a snippet which shows what is not working: https://ideone.com/AmQrkH
The Problem: The RedisObjectValue
is defined as Long
. When I am comparing it now with
players.filter(_.userId == 2)
for example, it doesn't give any results, even if there are players with userId
2, or to be more exact: 2l
.
For direct Long
it's not a problem.
players.filter(_._id == 2)
is working.
So is there any fix for that, so that comparable instances of classes to T
can also be compared to RedisObjectValue[T]
, and not just T
itself?
Replace this.get.equals(v)
with get == v
. (Removing this
is unrelated, just a good idea in general, the main thing is to use ==
instead of equals
).
Consider this:
scala> 2 equals 2L
res79: Boolean = false
scala> 2 == 2L
res80: Boolean = true