代码之家  ›  专栏  ›  技术社区  ›  olle kullberg

“MyType”问题:是否必须在Scala中使用抽象类型(或泛型)才能返回实际的类?

  •  9
  • olle kullberg  · 技术社区  · 14 年前

    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 )
    

    当我运行代码时,会得到以下输出:

    $ scala animal.scala 
    Dog(Fido,11)
    Dog(Dog: Fido,12)
    

    我想在 updateName updateWeight Animal ). 我知道如果我超越 直接返回正确的类型,而不必使用抽象类型 SubAnimal .

    对于抽象类型的值是 ?

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

    3 回复  |  直到 14 年前
        1
  •  6
  •   Alex Cruise    14 年前

    一些 recent discussion 关于这个话题。。。您要寻找的通常称为“MyType”,它的典型Scala/Java编码使用递归类型参数:

    public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable { 
        public final int compareTo(E o) 
        // ... 
    }
    
        2
  •  9
  •   Landei    14 年前

    这应该有效:

    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 class Cat(name: String, weight: Int) extends Animal[Dog] 被编译器拒绝。代码 改编自 http://oldfashionedsoftware.com/2009/12/10/self-help/

        3
  •  6
  •   one-zero-zero-one    14 年前

    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)
    }