Reputation: 190679
I have a class RBase, and a RInt class that inherits from it.
The Base has three interface functions. As the subclasses that inherit can use different type of values, the function parameter is typed as Any. As a result, I need to use asInstanceOf
to implement the subclasses. This is an example.
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)
I think Any
and asInstanceOf
can be removed using type parameters. This is my first try.
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)
Unfortunately, I have the following error messages.
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
Upvotes: 0
Views: 1001
Reputation: 9698
You were quite close with your idea. Parameterize the whole class instead of individual methods.
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: To answer why your code doesn't work - because you parameterized the method with a type called "Int". Compiler thinks it's just a name for the type (it can be T, U, Int, Whatever). So the return type is not a "real Int" in that case, but your made-up type.
Upvotes: 2