Anulación de tipo Scala

EDITED AFTER TWO ANSWERS BELOW I am trying to make the following Scala code to compile.

  abstract class C {
    type T <: C
    def x(other: T): (T, T)
  }

  class C1 extends C {
    override type T = C1
    override def x(other: C1): (C1, C1) = (this, this)
  }

  def doSthg(cs1 : List[C]) {
    val e1 = cs1(0)
    val e2 = cs1(1)

    e1.x(e2)
  }

Pero falla con el siguiente mensaje:

Description Resource    Path    Location    Type
type mismatch;  found   : e2.type (with underlying type Chromo[G])  required: e1.C  PI3.sc  /GA/src/org/jts/ga  line 76 Scala Problem
type mismatch;  found   : e2.type (with underlying type org.jts.ga.MI2.C)  required: e1.T   MI2.sc  /GA/src/org/jts/ga  line 18 Scala Problem

¿Alguna idea?

Básicamente, quiero definir una clase genérica como C arriba, y tengo métodos con el tipo correcto en una subclase (C1).

Todo es bueno hasta que se invoca un método genérico en C en soSthg.

Gracias

NUEVA SECCIÓN DE EDICIÓN

Gracias v much for your replies. Looking at the following code, I was hoping to avoid asInstanceOf.

  abstract class G[T](val t: T) {
    def ~(): G[T]
  }
  abstract class C[T](val g: List[G[T]]) {
    def x(other: C[T]): (C[T], C[T])
  }

  class G1(override val t: Boolean) extends G[Boolean](t){
    override def ~() = new G1(!t)
  }

  class C1(override val g: List[G1]) extends C[Boolean](g) {
    override def x(other: C[Boolean]): (C[Boolean], C[Boolean]) = {
      val go = other.g.map(e => e.asInstanceOf[G1])
      //val go = other.g
      val nc1 = new C1(go)
      (nc1, nc1)//for demo
    }
  }

La firma de x (otro: C [booleano]) es el problema.

Esto funcionaría:

def doSthg2[T <: C](csl : List[T]) { csl(0).x(csl(1)) }

¿Cómo evitar asInstanceOf?

0

2 Respuestas

C1 compiles fine. Note that you could remove override keyword here:

class C1 extends C {
  type T = C1
  def x(other: C1): (C1, C1) = (this, this)//do you mean (other, this)?
}

doSthg is just invalid: you can't prove that e2 is e1.T. This works as expected:

def doSthg(e1: C)(e2: e1.T) {
  e1.x(e2)
}

O esto:

abstract class C {
  ...
  def create(): T
}

def doSthg(e1: C) {
  val e2 = e1.create()
  e1.x(e2)
}

Para su método original doSthg x debería aceptar cualquier instancia de C :

trait C {
  def x(other: C): (C, C)
}
0
agregado

There's no problem defining C & C1 as above. The problem is that you're passing an argument to e1.x that is of type C (not C1) and so violates your C1.x method signature.

En lo que respecta al compilador:

  1. You're modelling a type hierarchy rooted at trait/class C
  2. Inside doSthg, the vals e1 & e2 are each of some type within the hierarchy. For e1 & e2, the only things known for sure are that e1.type and e2.type are each subtypes of C. There's no guarantee that e1 and e2 are of the same type (or are subtypes of one another) - even though the class hierarchy is very shallow (just one subclass, C1). You could extend by adding new subtypes of C in new .class/.jar files at any point in the future (possibly generated from .scala/.java files from this compiler on this machine, or even by a different compiler on a different machine!)
  3. You have chosen that your method C1.x is not flexible - it's argument must be of type C1, not any C. Hence, e1.x cannot take an 'arbitrary' e2 <: C as argument.

Entonces, el compilador está haciendo lo correcto, en función de sus decisiones de diseño. Soluciones:

  • allow C1.x to take arguments of type C
  • make doSthg argument List[C1] (possibly moving doSthg within C1 at the same time)
0
agregado
En efecto. Algo así funcionaría: def doSthg2 [T <: C] (csl: Lista [T]) {csl (0) .x (csl (1))}
agregado el autor jts, fuente