【问题标题】:Clarification needed about Scala variance and type bounds需要澄清 Scala 方差和类型界限
【发布时间】:2012-03-05 16:02:41
【问题描述】:

我有一个定义如下的 scala 特征:

trait AdvertisementDAO[A <: Advertisement] extends CrudRepository[A, Integer] {
...

我希望能够获得该 DAO 的一个实例,该实例适用于 Advertisement 的子类或基类 Advertisement 本身。我不确定如何达到预期的效果。

这是我尝试过的:

@Inject
var advertisementDAO: AdvertisementDAO[+Advertisement] = _

谁能帮忙?

【问题讨论】:

    标签: scala variance type-bounds


    【解决方案1】:

    看起来您正在尝试将特征 AdvertisementDAO 的类型参数 A 定义为协变。下面是上一个答案中使用协方差注释 + 的代码示例的变体。

    trait Advertisement {}
    
    class AdvertisementImpl extends Advertisement{}
    
    class CrudRepository[+A,B]  {}
    
    trait AdvertisementDAO[+A <: Advertisement] extends CrudRepository[A, Integer] {}
    
    class AdvertisementDAOImpl[+A <: Advertisement] extends AdvertisementDAO[A]{}
    
    class AdvertisementDAOImpl2 extends AdvertisementDAO[AdvertisementImpl]{}
    
    class AdvertisementDAOImpl3 extends AdvertisementDAO[Advertisement]{}
    
    object Tester
    {
      def main(args:Array[String]):Unit =
      {
        var advertisementDAO: AdvertisementDAO[Advertisement] = null
        advertisementDAO = new AdvertisementDAOImpl
        advertisementDAO = new AdvertisementDAOImpl2 
        advertisementDAO = new AdvertisementDAOImpl3
      }
    }
    

    协变泛型的另一个例子是 scala.collection.immutable.List。将泛型(类或特征)C 定义为协变意味着 C[S] 是 C[T] 的子类型,如果类型 S 是类型 T 的子类型。例如,AdvertisementDAO[AdvertisementImpl] 是 AdvertisementDAO[Advertisement ] 因为 AdvertisementImpl 是 Advertisement 的子类型(因为 AdvertisementImpl 扩展了 Advertisement)。我发布了一个paper,其中包含关于在许多语言(例如 Scala、C#、Java)中出现的方差的教程。 Slides 也可用于快速概览。希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      我尝试了很多组合,但我收到了一个使用 scala 2.9.1 编译的组合

        var advertisementDAO: AdvertisementDAO[_ <:Advertisement] = _
      
        advertisementDAO = new AdvertisementDAOImpl
      
        advertisementDAO = new AdvertisementDAOImpl2 
      
        advertisementDAO = new AdvertisementDAOImpl3
      

      我的代码:

      trait Advertisement {}
      
      class AdvertisementImpl extends Advertisement{}
      
      class CrudRepository[A,B]  {}
      
      trait AdvertisementDAO[ A <: Advertisement] extends CrudRepository[A, Integer] {}
      
      class AdvertisementDAOImpl[A <: Advertisement] extends AdvertisementDAO[A]{}
      
      class AdvertisementDAOImpl2 extends AdvertisementDAO[AdvertisementImpl]{}
      
      class AdvertisementDAOImpl3 extends AdvertisementDAO[Advertisement]{}
      

      【讨论】:

      • 感谢 Ajozwik,Advertisment 是 JPA 实体而不是 trait。 Crud 存储库是一个 Spring 数据接口。您知道如何确保只能使用广告基类或其子类,而不是此处的任何类:var advertisementDAO: AdvertisementDAO[_]
      • 试试var advertisementDAO: AdvertisementDAO[_ &lt;:Advertisement] = _
      猜你喜欢
      • 2021-01-24
      • 2013-05-31
      • 1970-01-01
      • 1970-01-01
      • 2011-07-24
      • 2013-09-28
      • 2013-09-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多