Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics &引用;MyType“;问题:我是否必须在Scala中使用抽象类型(或泛型)来返回实际的类?_Generics_Scala - Fatal编程技术网

Generics &引用;MyType“;问题:我是否必须在Scala中使用抽象类型(或泛型)来返回实际的类?

Generics &引用;MyType“;问题:我是否必须在Scala中使用抽象类型(或泛型)来返回实际的类?,generics,scala,Generics,Scala,我不确定是否有更好的方法: trait Animal { val name: String val weight: Int type SubAnimal <: Animal def updateName(n: String) = returnMe(n, this.weight) def updateWeight(w: Int) = returnMe(this.name, w) // Abstract protected method protected de

我不确定是否有更好的方法:

trait Animal {
  val name: String
  val weight: Int

  type SubAnimal <: Animal

  def updateName(n: String) = returnMe(n, this.weight)
  def updateWeight(w: Int) = returnMe(this.name, w)
  // Abstract protected method
  protected def returnMe(n: String, w: Int): SubAnimal
}

case class Dog(name: String, weight: Int) extends Animal {
  type SubAnimal = Dog
  override def returnMe(n: String, w: Int): Dog = Dog("Dog: " + name, w)
}
case class Cat(name: String, weight: Int) extends Animal {
  type SubAnimal = Cat
  override def returnMe(n: String, w: Int): Cat = Cat("Cat: " + name, w)
}

val fido = Dog("Fido", 11)
println( fido )
val fido2 = fido.updateWeight(12)
println( fido2 )
我想在调用
updateName
updateView
后返回问题动物的实际类型(即非
animal
)。我知道如果我直接重写
updateName
updateView
,那么将返回正确的类型,并且我不必使用抽象类型
SubAnimal

对于抽象类型的值与子类的值相同的特殊情况,是否有一些巧妙的方法来转义抽象类型


(这就是所谓的“MyType”问题)。

使用类型参数化

trait Animal[A <: Animal[A]] {
  val name: String
  val weight: Int

  def updateName(n: String) = returnMe(n, this.weight)
  def updateWeight(w: Int) = returnMe(this.name, w)
  // Abstract protected method
  protected def returnMe(n: String, w: Int): A
}

case class Dog(name: String, weight: Int) extends Animal[Dog] {
  override def returnMe(n: String, w: Int) = Dog("Dog: " + name, w)
}

case class Cat(name: String, weight: Int) extends Animal[Cat] {
  override def returnMe(n: String, w: Int) = Cat("Cat: " + name, w)
}
trait Animal[A关于这个主题的一些人……您所寻找的通常被称为“MyType”,它的典型Scala/Java编码使用递归类型参数:

public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable { 
    public final int compareTo(E o) 
    // ... 
}
公共抽象类Enum实现可比较的、可序列化的{
公共最终国际比较(E/o)
// ... 
}
这应该可以:

trait Animal[T] {
  self:T =>

  val name: String
  val weight: Int

  def updateName(n: String): T = returnMe(n, this.weight)
  def updateWeight(w: Int): T = returnMe(this.name, w)
  // Abstract protected method
  protected def returnMe(n: String, w: Int): T
}

case class Dog(name: String, weight: Int) extends Animal[Dog] {
  override def returnMe(n: String, w: Int): Dog = Dog("Dog: " + name, w)
}

case class Cat(name: String, weight: Int) extends Animal[Cat] {
   override def returnMe(n: String, w: Int): Cat = Cat("Cat: " + name, w)
}

<> >像 case类CAT(name:String,Bug:int)扩展了动物[狗] /代码>被编译器拒绝。从

HMM中修改的代码被盗。您的解决方案大概是“抽象类型”的意思。我认为“类型参数化”和“抽象类型”一样坏/好。在这种情况下。你同意吗?@olle:我从来都不理解抽象类型成员的意义,也从来没有在我自己的代码中使用过它们。我认为它们是语言中不必要的冗余。(Paul P最近在邮件列表中表达了类似的想法。)你是对的,抽象类型似乎是纯粹的糖。但我非常喜欢它们,因为我认为更容易考虑“类型字段”您可以在子类中重写它,而不是相应的类型参数语法。抽象类型不仅仅是语法上的糖。虽然您通常可以将抽象类型版本转换为泛型版本,反之亦然,但它们并不等价:如果您有Foo[X],则像Foo[Int]这样的每个实例化都会建立一个新类型。如果您有Foo{type X},只有一个Foo类型,它恰好包含一个抽象类型变量。因此,神奇的方法是使用“this.type”(从您的链接),但由于我返回了一个新实例(不是this)那么这是不可能的。在后面的文章中,奥德斯基推荐了这个问题的抽象类型,所以我想讨论到此结束。谢谢。是的,this.type太窄了,不能充当MyType:它是这个类型,但没有这个类的其他实例。嗨@Landei,我看不出这和@one-zero-one提供的解决方案之间有什么区别。为什么需要self:T=>部分?当我把它拿走时,我得到了相同的输出。@olle:行为与一零一的解决方案相同,只是更容易阅读。没有self:T部分,您可以编写
case类Cat(name:String,weight:Int)扩展Animal[Int]
,这显然是不允许的。有关详细信息,请参阅我提供的链接。
trait Animal[T] {
  self:T =>

  val name: String
  val weight: Int

  def updateName(n: String): T = returnMe(n, this.weight)
  def updateWeight(w: Int): T = returnMe(this.name, w)
  // Abstract protected method
  protected def returnMe(n: String, w: Int): T
}

case class Dog(name: String, weight: Int) extends Animal[Dog] {
  override def returnMe(n: String, w: Int): Dog = Dog("Dog: " + name, w)
}

case class Cat(name: String, weight: Int) extends Animal[Cat] {
   override def returnMe(n: String, w: Int): Cat = Cat("Cat: " + name, w)
}