Is there a way to create a generic class with a trait or mixin that is a subtype of a type parameter

I am trying to connect additional data to other types and have a property like this:

trait ExtraData {
  def getExtraData() : Array[Byte]
}

      

And I am currently using it like this:

class ExternalType1WithExtraData(superType:ExternalType1, bytes:Array[Byte]) extends ExternalType1(superType.a,superType.b, ...) with ExtraData {
  def getExtraData() : Array[Byte] = bytes
}

class ExternalType2WithExtraData(superType:ExternalType2, bytes:Array[Byte]) extends ExternalType2(superType.z,superType.w, ...) with ExtraData {
  def getExtraData() : Array[Byte] = bytes
}

      

There seems to be a general way to create these classes, but I haven't been able to find one yet.

--- Start Editing - Add the desired behavior

For function

def sendData(ex : ExternalType1)

      

I want my extended types to be passed to this function.

val data:ExternalType1 = ???
val moredata:ExternalType1 = { new ExternalType1 with ExtraData{...} }
sendData(moredata)

      

--- End Edit

I tried to do something along these lines but with no success:

// Compiler wont let me extend T
class WithExtraData[T](bytes:Array[Byte]) extends T with ExtraData{
  def getExtraData() : Array[Byte] = bytes
}

      

: 12: error: class type required, but T found class WithExtraDataT extends T with ExtraData {^: 12: error: illegal inheritance; supertype T is not a subclass of the superclass object of the mixin property ExtraData class WithExtraDataT extends T with ExtraData {

// Seems closer, but doesn't work.
class WithExtraData[T](t:T, bytes:Array[Byte]) extends ExtraData {
  this : T => t
  def getExtraData() : Array[Byte] = bytes
}

      

: 13: warning: pure expression does nothing at operator position; multi-line expressions may require parentheses included self: T => t ^ specific class WithExtraData p>

scala> new WithExtraData [String] ("hi", new ArrayByte): 13: error: class WithExtraData could not be created because it does not match its self-supporting WithExtraData [String] with a string

Is there a way to achieve this?

+3


source to share


2 answers


I think the closest you can reasonably get to (at least no macros) is not an extension ExternalType1

, but an implicit conversion instead:

class WithExtraData[T](val value: T, bytes: Array[Byte]) extends ExtraData {
  def getExtraData(): Array[Byte] = bytes
}

object WithExtraData {
  implicit def getValue[T](x: WithExtraData[T]): T = x.value
}

      



Then you can, for example, pass WithExtraData[ExternalType1]

when required ExternalType1

.

+2


source


Are you basically trying to enrich your types with additional type information represented by values, if I understand you correctly? In this case, the concept you are looking for is called dependent types

Scala doesn't support this concept natively (like Idris). However, there are some workarounds.



One example would be using Shapeless

import shapeless._
import SingletonTypes._

val test1: ^((20 + 50) > 1) = true
test1: Boolean(true) = true

val test2: ^((20 + 50) > 1) = false
<console>:11: error: type mismatch;
 found   : Boolean(false)
 required: Boolean(true)

      

0


source







All Articles