2016-03-29 13 views
0

Ich habe eine Klasse RBase und eine RInt-Klasse, die davon erbt. Die Base verfügt über drei Schnittstellenfunktionen. Da die Unterklassen, die erben, unterschiedliche Arten von Werten verwenden können, wird der Funktionsparameter als Any eingegeben. Als Ergebnis muss ich asInstanceOf verwenden, um die Unterklassen zu implementieren. Dies ist ein Beispiel.Typ Parameter vs Any in Scala

abstract class RBase(val name:String) 
{ 
    def encode(value:Any) : Array[Byte] 
    def decode(byteArray: Array[Byte]) : Any 

    def check(value:Any) : Boolean 
} 

class RInt extends RBase("int") 
{ 
    override def encode(value: Any) = { 
     val byteValue = value.asInstanceOf[Int] 
     Array[Byte](byteValue.toByte, byteValue.toByte, byteValue.toByte) 
    } 
    override def decode(byteArray: Array[Byte]) : Any = { 
     byteArray.size 
    } 
    override def check(value:Any) : Boolean = { 
     val byteValue = value.asInstanceOf[Int] 
     if (byteValue.toInt > 0) true 
     else false 
    } 
} 


object Main extends App { 
    val b = new RInt 
    println(b.decode(Array[Byte]())) 
    println(b.encode(100).mkString(":")) 
    println(b.check(-1)) 
} 

// uncomment when compile 
Main.main(args) 

Ich denke Any und asInstanceOf können mit Typparametern entfernt werden. Dies ist mein erster Versuch.

abstract class TBase(val name:String) 
{ 
    def encode[T](value:T) : Array[Byte] 
    def decode[T](byteArray: Array[Byte]) : T 
    def check[T](value:T) : Boolean 
} 

class TInt extends TBase("bit") 
{ 
    override def encode[Int](value: Int) = { 
     Array[Byte](value.toByte, value.toByte, value.toByte) 
    } 
    override def decode[Int](byteArray: Array[Byte]) : Int = { 
     byteArray.size 
    } 
    override def check[Int](value:Int) : Boolean = { 
     if (value > 0) true 
     else false 
    } 
} 

object Main extends App { 
    val b = new TInt 
    println(b.decode(Array[Byte]())) 
} 

// uncomment when compile 
Main.main(args) 

Leider habe ich die folgenden Fehlermeldungen.

T.scala:11: error: value toByte is not a member of type parameter Int 
     Array[Byte](value.toByte, value.toByte, value.toByte) 
         ^
T.scala:11: error: value toByte is not a member of type parameter Int 
     Array[Byte](value.toByte, value.toByte, value.toByte) 
             ^
T.scala:11: error: value toByte is not a member of type parameter Int 
     Array[Byte](value.toByte, value.toByte, value.toByte) 
                ^
T.scala:14: error: type mismatch; 
found : scala.Int 
required: Int(in method decode) 
     byteArray.size 
       ^
T.scala:17: error: value > is not a member of type parameter Int 
     if (value > 0) true 
       ^
5 errors found 
  • Q1: Wie Rbase Ansatz zu verbessern, dass jede und asInstanceOf verwendet?
  • Q2: Was ist falsch an TBase?

Antwort

2

Sie waren ziemlich nah mit Ihrer Idee. Parametriere die gesamte Klasse anstatt einzelner Methoden.

abstract class TBase[T](val name: String) { 
    def encode(value: T): Array[Byte] 
    def decode(byteArray: Array[Byte]): T 
    def check(value: T): Boolean 
} 

class TInt extends TBase[Int]("bit") { 
    override def encode(value: Int) = { 
    Array[Byte](value.toByte, value.toByte, value.toByte) 
    } 
    override def decode(byteArray: Array[Byte]): Int = { 
    byteArray.size 
    } 
    override def check(value: Int): Boolean = { 
    if (value > 0) true 
    else false 
    } 
} 

EDIT: Um zu beantworten, warum Ihr Code nicht funktioniert - weil Sie die Methode mit einem Typ namens "Int" parametrisiert. Compiler denkt, dass es nur ein Name für den Typ ist (es kann T, U, Int, was auch immer sein). Daher ist der Rückgabetyp in diesem Fall kein "echter Int", sondern Ihr erfundener Typ.