복붙노트

[SCALA] "합니다 MyType"문제 :해야합니까 실제 클래스를 반환하는 스칼라에서 추상적 인 유형 (또는 제네릭)를 사용해야?

SCALA

"합니다 MyType"문제 :해야합니까 실제 클래스를 반환하는 스칼라에서 추상적 인 유형 (또는 제네릭)를 사용해야?

이 일을 더 나은 방법이 있는지 확실하지 않다 :

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가 (즉,없는 동물)를 호출 한 후 문제가되는 동물의 실제 타입을 반환합니다. 내가 직접 updateName 및 updateWeight를 오버라이드 (override)하는 경우는, 올바른 형식이 반환됩니다 내가 추상 형 SubAnimal을 사용하지 않는 것을 알고있다.

추상 형식의 값이 서브 클래스와 동일한 특별한 경우에 대한 추상 형식을 탈출의 몇 가지 교묘 한 방법이 있나요?

(이것은 "합니다 MyType"문제로 알고 있습니다).

해결법

  1. ==============================

    1.이 주제에 대한 최근의 논의는 ... 당신이 일반적으로 "합니다 MyType"과의 일반적인 스칼라 / 자바 인코딩라고 찾고있는 것은 재귀 유형 매개 변수를 사용합니다 :

    이 주제에 대한 최근의 논의는 ... 당신이 일반적으로 "합니다 MyType"과의 일반적인 스칼라 / 자바 인코딩라고 찾고있는 것은 재귀 유형 매개 변수를 사용합니다 :

    public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable { 
        public final int compareTo(E o) 
        // ... 
    }
    
  2. ==============================

    2.이 작업을해야합니다 :

    이 작업을해야합니다 :

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

    경우 클래스 고양이 (: 문자열, 무게 : 이름 INT)와 같은 뭔가 동물이 [개] 컴파일러에 의해 거부됩니다 확장합니다. 코드 도난은 http://oldfashionedsoftware.com/2009/12/10/self-help/에서 적응

  3. ==============================

    3.형식 매개 변수화를 사용하십니까?

    형식 매개 변수화를 사용하십니까?

    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)
    }
    
  4. from https://stackoverflow.com/questions/3962219/mytype-problem-do-i-have-to-use-abstract-types-or-generics-in-scala-to-retu by cc-by-sa and MIT license