【问题标题】:Ensure arguments to generic method have same type in trait method确保泛型方法的参数在 trait 方法中具有相同的类型
【发布时间】:2020-08-27 01:56:45
【问题描述】:

我有一个密封特性和一些扩展该特性的案例类,如下所示:

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 上。我可以将method 设为通用而不“感染”其余特征吗?
  2. 我实际上不确定我的类型限制是否能得到我想要的结果。谁能确认我的直觉是否正确?

【问题讨论】:

  • 不要使用T : Foo,使用T <: Foo。我相信前者是上下文绑定的,而 Foo 没有类型参数
  • Bar, Baz 应该是 Bar(), Baz(),因为它们是案例类。

标签: scala generics traits


【解决方案1】:

如果你愿意的话

确保arg1arg2 始终具有相同的类型;也就是说,它们都应该是BarBaz,并且不能混合使用

然后

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()) 编译。

更多关于广义类型约束(&lt;:&lt;, =:=甚至&lt;:!&lt;, =:!=)应该优先于类型边界(&lt;:&gt;:)的细节可以在这里找到:

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/

【讨论】:

    【解决方案2】:

    您需要指定&lt;:

    : 代表context bound 并与trait Zoo[T] 等类型类结合使用

    &lt;: 代表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)
    

    【讨论】:

    • 啊,所以我误解了: 对类型参数的含义。谢谢!
    • @IvanStanislavciuc 抱歉,def method[T &lt;: Foo](arg1: T, arg2: T) 不正确。请参阅我的答案中的详细信息。
    猜你喜欢
    • 1970-01-01
    • 2013-07-27
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 2014-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多