确保泛型方法的参数在特征方法中具有相同的类型

Ensure arguments to generic method have same type in trait method

我有一个密封的特性和一些扩展该特性的案例 类,像这样:

sealed trait Foo
case class Bar extends Foo
case class Baz extends Foo

在我的代码的不同部分,我有一个特征,它有一个在 Foos

上运行的方法
trait Example {
    def method(arg1: Foo, arg2: Foo)
}

但是,我真的很想确保 arg1arg2 始终具有相同的类型;也就是说,它们应该都是 BarBaz,而不能混用。我的第一直觉是使用泛型:

trait Example {
    def method[T: Foo](arg1: T, arg2: T)
}

但是我运行遇到了两个问题:

    据我所知,
  1. T 需要出现在 Example 上。我可以在没有 "infecting" 其余特征的情况下使 method 通用吗?
  2. 我不确定我的类型限制是否能得到我想要的结果。谁能证实我的直觉是否正确?

您需要指定<:

: 代表 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/