确保泛型方法的参数在特征方法中具有相同的类型
Ensure arguments to generic method have same type in trait method
我有一个密封的特性和一些扩展该特性的案例 类,像这样:
sealed trait Foo
case class Bar extends Foo
case class Baz extends Foo
在我的代码的不同部分,我有一个特征,它有一个在 Foo
s
上运行的方法
trait Example {
def method(arg1: Foo, arg2: Foo)
}
但是,我真的很想确保 arg1
和 arg2
始终具有相同的类型;也就是说,它们应该都是 Bar
或 Baz
,而不能混用。我的第一直觉是使用泛型:
trait Example {
def method[T: Foo](arg1: T, arg2: T)
}
但是我运行遇到了两个问题:
据我所知,T
需要出现在 Example
上。我可以在没有 "infecting" 其余特征的情况下使 method
通用吗?
- 我不确定我的类型限制是否能得到我想要的结果。谁能证实我的直觉是否正确?
您需要指定<:
:
代表 context bound 并与类型 class 结合使用,例如 trait Zoo[T]
<:
代表upper type bound
trait Example {
def method[T <: Foo](arg1: T, arg2: T)
}
更新:
正如@Dmytro Mitin 正确指出的那样,正确的解决方案需要执行证据检查=:=
。
def method[T <: Foo, U <: Foo](arg1: T, arg2: U)(implicit ev: T =:= U)
其实如果你想
to ensure that arg1
and arg2
always have the same type; that is, they should both be either Bar
or Baz
, and never a mix
然后
trait Example {
def method[T <: Foo](arg1: T, arg2: T) = ???
}
不正确。 new Example {}.method(Bar(), Baz())
编译因为 T
被推断为 Foo
.
正确的是
trait Example {
def method[T <: Foo, U <: Foo](arg1: T, arg2: U)(implicit ev: T =:= U) = ???
}
然后 new Example {}.method(Bar(), Baz())
不编译但 new Example {}.method(Bar(), Bar())
和 new Example {}.method(Baz(), Baz())
编译。
有关广义类型约束 (<:<
, =:=
and even <:!<
, =:!=
) 优先于类型边界 (<:
、>:
) 的更多详细信息,请参见此处:
https://blog.bruchez.name/2015/11/generalized-type-constraints-in-scala.html(参见示例
def tupleIfSubtype[T <: U, U](t: T, u: U) = (t, u)
对比
def tupleIfSubtype[T, U](t: T, u: U)(implicit ev: T <:< U) = (t, u)
有。)
https://apiumhub.com/tech-blog-barcelona/scala-generics-generalized-type-constraints/ (https://dzone.com/articles/scala-generics-generalized-type-constraints-part-3)
https://herringtondarkholme.github.io/2014/09/30/scala-operator/
我有一个密封的特性和一些扩展该特性的案例 类,像这样:
sealed trait Foo
case class Bar extends Foo
case class Baz extends Foo
在我的代码的不同部分,我有一个特征,它有一个在 Foo
s
trait Example {
def method(arg1: Foo, arg2: Foo)
}
但是,我真的很想确保 arg1
和 arg2
始终具有相同的类型;也就是说,它们应该都是 Bar
或 Baz
,而不能混用。我的第一直觉是使用泛型:
trait Example {
def method[T: Foo](arg1: T, arg2: T)
}
但是我运行遇到了两个问题:
-
据我所知,
T
需要出现在Example
上。我可以在没有 "infecting" 其余特征的情况下使method
通用吗?- 我不确定我的类型限制是否能得到我想要的结果。谁能证实我的直觉是否正确?
您需要指定<:
:
代表 context bound 并与类型 class 结合使用,例如 trait Zoo[T]
<:
代表upper type bound
trait Example {
def method[T <: Foo](arg1: T, arg2: T)
}
更新:
正如@Dmytro Mitin 正确指出的那样,正确的解决方案需要执行证据检查=:=
。
def method[T <: Foo, U <: Foo](arg1: T, arg2: U)(implicit ev: T =:= U)
其实如果你想
to ensure that
arg1
andarg2
always have the same type; that is, they should both be eitherBar
orBaz
, and never a mix
然后
trait Example {
def method[T <: Foo](arg1: T, arg2: T) = ???
}
不正确。 new Example {}.method(Bar(), Baz())
编译因为 T
被推断为 Foo
.
正确的是
trait Example {
def method[T <: Foo, U <: Foo](arg1: T, arg2: U)(implicit ev: T =:= U) = ???
}
然后 new Example {}.method(Bar(), Baz())
不编译但 new Example {}.method(Bar(), Bar())
和 new Example {}.method(Baz(), Baz())
编译。
有关广义类型约束 (<:<
, =:=
and even <:!<
, =:!=
) 优先于类型边界 (<:
、>:
) 的更多详细信息,请参见此处:
https://blog.bruchez.name/2015/11/generalized-type-constraints-in-scala.html(参见示例
def tupleIfSubtype[T <: U, U](t: T, u: U) = (t, u)
对比
def tupleIfSubtype[T, U](t: T, u: U)(implicit ev: T <:< U) = (t, u)
有。)
https://apiumhub.com/tech-blog-barcelona/scala-generics-generalized-type-constraints/ (https://dzone.com/articles/scala-generics-generalized-type-constraints-part-3)
https://herringtondarkholme.github.io/2014/09/30/scala-operator/