将通用类型的包装器对象与与内部类型相当的所有对象进行比较?
Comparing wrapper object of generic type to with everything that is comparable to inner type?
我正在尝试围绕保存在 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
}
}
所以,正如我所说,一切正常。
除了比较的东西。为此,假设我有一个 class Player
两个值,userId
和 name
.
class Player {
val userId = RedisObjectValue("userId", 0)
val name = RedisObjectValue("player", "Unknown")
}
现在我有一个玩家列表,想要过滤以获取名称为 "Unknown" 的所有玩家。
list.filter(_.name == "Unknown")
这是行不通的。如果我扩展过滤器过滤器调用并编写一个函数,它会在 IntelliJ "Comparing unrelated types".
中告诉我
是的,我明白它在告诉我什么,但我想解决这个问题。我的意思是我可以很容易地将 Long 与 Int 和类似的东西进行比较,所以必须有一种方法可以使它们具有可比性,对吗?
在上面的代码中,我什至写了使用与内部类型比较的 equals 函数,但似乎没有使用它。
当然,我总是可以对值调用 .get
,例如 players.filter(_.name.get == "Unknown")
,但这有点脏,我希望避免这种情况。
编辑:经过一些分析发现了真正的问题
上面还是旧文,待会儿再解释一下。
我有一个片段显示什么不起作用:https://ideone.com/AmQrkH
问题:RedisObjectValue
被定义为 Long
。当我现在将它与
进行比较时
players.filter(_.userId == 2)
例如,它不会给出任何结果,即使有 userId
2 的玩家,或者更准确地说:2l
.
直接Long
没问题。
players.filter(_._id == 2)
正在工作。
那么是否有任何解决方法,以便 classes 与 T
的可比较实例也可以与 RedisObjectValue[T]
进行比较,而不仅仅是 T
本身?
将 this.get.equals(v)
替换为 get == v
。 (删除this
是无关紧要的,总的来说只是一个好主意,主要是使用==
而不是equals
)。
考虑一下:
scala> 2 equals 2L
res79: Boolean = false
scala> 2 == 2L
res80: Boolean = true
我正在尝试围绕保存在 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
}
}
所以,正如我所说,一切正常。
除了比较的东西。为此,假设我有一个 class Player
两个值,userId
和 name
.
class Player {
val userId = RedisObjectValue("userId", 0)
val name = RedisObjectValue("player", "Unknown")
}
现在我有一个玩家列表,想要过滤以获取名称为 "Unknown" 的所有玩家。
list.filter(_.name == "Unknown")
这是行不通的。如果我扩展过滤器过滤器调用并编写一个函数,它会在 IntelliJ "Comparing unrelated types".
中告诉我
是的,我明白它在告诉我什么,但我想解决这个问题。我的意思是我可以很容易地将 Long 与 Int 和类似的东西进行比较,所以必须有一种方法可以使它们具有可比性,对吗?
在上面的代码中,我什至写了使用与内部类型比较的 equals 函数,但似乎没有使用它。
当然,我总是可以对值调用 .get
,例如 players.filter(_.name.get == "Unknown")
,但这有点脏,我希望避免这种情况。
编辑:经过一些分析发现了真正的问题
上面还是旧文,待会儿再解释一下。
我有一个片段显示什么不起作用:https://ideone.com/AmQrkH
问题:RedisObjectValue
被定义为 Long
。当我现在将它与
players.filter(_.userId == 2)
例如,它不会给出任何结果,即使有 userId
2 的玩家,或者更准确地说:2l
.
直接Long
没问题。
players.filter(_._id == 2)
正在工作。
那么是否有任何解决方法,以便 classes 与 T
的可比较实例也可以与 RedisObjectValue[T]
进行比较,而不仅仅是 T
本身?
将 this.get.equals(v)
替换为 get == v
。 (删除this
是无关紧要的,总的来说只是一个好主意,主要是使用==
而不是equals
)。
考虑一下:
scala> 2 equals 2L
res79: Boolean = false
scala> 2 == 2L
res80: Boolean = true