2016-03-29 6 views
0

У меня есть класс RBase и класс RInt, который наследуется от него. База имеет три функции интерфейса. Поскольку подклассы, которые наследуют, могут использовать разные типы значений, параметр функции вводится как Any. В результате мне нужно использовать asInstanceOf для реализации подклассов. Это пример.Параметр параметра vs Any в 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) 

Я думаю Any и asInstanceOf может быть удален с помощью параметров типа. Это моя первая попытка.

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) 

К сожалению, у меня есть следующие сообщения об ошибках.

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: Как улучшить RBase подход, который использует любой и asInstanceOf?
  • Q2: Что не так с TBase?

ответ

2

Вы были очень близки своей идее. Параметрируйте весь класс вместо отдельных методов.

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: Ответьте, почему ваш код не работает, поскольку вы параметризовали метод с типом, называемым «Int». Компилятор считает, что это просто имя для типа (это могут быть T, U, Int, Whatever). Таким образом, тип возврата не является «реальным Int» в этом случае, но ваш готовый тип.