嵌套泛型是否有Scala模式,允许我的内部泛型类型具有多态性? [英] Is there a Scala pattern for nested generics allowing my inner generic type to have polymorphism?

查看:77
本文介绍了嵌套泛型是否有Scala模式,允许我的内部泛型类型具有多态性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望能够在外部嵌套泛型类的函数中传递相同类型的参数,但是还具有多态内部泛型类-允许我对InnerShell和两者都外壳.在Scala中甚至有可能吗?

I want to be able to pass a parameter of the same type in a function in the outer nested generic class, but also have a polymorphic internal generic class as well - allowing me to use an abstract base class/trait for InnerShell and OuterShell both. Is this even possible in Scala?

class OuterShellClass[Generic] {
  def doSomething(param : OuterShellClass[Generic]) : OuterShellClass[Generic] = this;
}

abstract class InnerShellClass[Type] {

}

class InnerShellSubclass[Type] extends InnerShellClass[Type]{

}
class wrapper{
  val obj : OuterShellClass[InnerShellClass[String]] = new OuterShellClass[InnerShellSubclass[String]];
}

如果OuterShellClass是不变式,则会出现错误:

If the OuterShellClass is a invariant, I get the error:

Note: InnerShellSubclass[String] <: InnerShellClass[String], but class OuterShellClass is invariant in type Generic

如果OuterShellClass是协变的,则会出现错误:

If the OuterShellClass is covariant, I get the error:

covariant type Generic occurs in contravariant position in type OuterShellClass[Generic] of value param

更新:

考虑到这一点,此快速技巧将起作用-请告诉我有更好的解决方案.由于OuterShellClass函数内部的泛型实际上是在类创建时独立于泛型定义的-不一定是同一类-我不能保证在运行时兼容的类.将这些特定的函数移到全局函数类中,这样我就可以收回保证并获得解决方案.我真的需要像这样细分我的课程吗?有更好的解决方案吗?

As I am thinking about it, this quick hack will work - please tell me there is a better solution. Since the generics inside OuterShellClass functions are effectively independent of the generic definition at class creation - not necessarily the same class - I cannot guarantee compatible classes at runtime. Move these specific functions to a global function class so I can reclaim the guarantee and get a solution. Do I really need to fragment my classes like this? Is there a better solution?

class OuterShellClass[+Generic] {
}

class Helper {
  def doSomething[T] (param1: OuterShellClass[T], param2: OuterShellClass[T]) =  param1;
}

abstract class InnerShellClass[Type] {

}

class InnerShellSubclass[Type] extends InnerShellClass[Type]{

}
class wrapper{
  val obj : OuterShellClass[InnerShellClass[String]] = new OuterShellClass[InnerShellSubclass[String]];
}

推荐答案

首先编写代码-后面进行说明.

Code first - explanations after.

class OuterShellClass[+Generic] {
}

object OuterShellClass {
  def doSomething[T] (param1: OuterShellClass[T], param2: OuterShellClass[T]): OuterShellClass[T] =  param1
}

abstract class InnerShellClass[Type] {

}

class InnerShellSubclass[Type] extends InnerShellClass[Type]{

}
class wrapper{
  val obj : OuterShellClass[InnerShellClass[String]] = new OuterShellClass[InnerShellSubclass[String]]
  val result : OuterShellClass[InnerShellClass[String]] = OuterShellClass.doSomething(obj,new OuterShellClass[InnerShellSubclass[String]])
}

正如我能够找到的那样,Scala对多态性有独特的看法,该观点要求数组的所有元素都完全属于同一类(带有警告).结果,其他语言(尤其是Java)的人发现,即使使用协方差和逆方差,多态性也违反了Scala泛型内部的期望.在此示例中,doSomething(ISubClass1 a,ISubClass2 b)是编译错误.在多态下,这样做是合法的,但在Scala泛型内部是不允许的.的第一个版本:

As I have been able to track down, Scala has a unique view on polymorphism connected to requiring all elements of an array belong to exactly the same class (with caveats). As a consequences, those from other languages (Java in particular) find polymorphism breaks expectations inside Scala generics, even when using covariance and contravariance. In this example, doSomething(ISubClass1 a, ISubClass2 b) is a compile error. Under polymorphism, it is legitimate to do this, but is not permitted inside Scala generics. The first version of this:

class OuterShellClass[+Generic] {
   def doSomething(param: OuterShellClass[Generic]): OuterShellClass[Generic] =  this
}

在这种情况下,不要求参数的类别与周围对象的类别相同,从而导致需要'contravariance'的错误,这种错误在这种情况下是无法满足的.我发现解决此问题的唯一方法是引用通用类型(在本例中为通用)的shift方法,并将它们移动到可以明确建立这些限制的伴随对象中的函数-该对象没有通用且该通用中函数不是协方差的.这符合Scala的要求,即容器仅具有一类对象(带有警告),同时仍允许在内部泛型类中使用某些多态性.

there is no requirement the class of param is the same as the class of the surrounding object in this case, causing the error requiring 'contravariance' which is impossible to meet in this context. The only way I have found to fix this is shift methods which reference the generic type (Generic in this case) and move them to a function in the companion object where these restrictions can be explicitly established - the object has no generics and the generics in the function are not covariance. This meets Scala requirements that containers have exactly one class of objects (with caveats) while still permitting use of some polymorphism in the inside generic class.

希望您通过Scala泛型的旅程比我自己的旅程更顺畅...

May your journey through Scala generics be smoother than my own...

这篇关于嵌套泛型是否有Scala模式,允许我的内部泛型类型具有多态性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆