2017-05-04 8 views
3

のサブタイプである形質またはミックスインと汎用的なクラスを作成する方法がありますです:私は他のタイプに余分なデータを添付して、に似た特性を持つようにしようとしているタイプのパラメータ

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

そして、私は現在、このようにそれを使用しています:

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 
} 

これらのクラスを作成するための一般的な方法が存在することになるようだが、私はまだそれを見つけることができませんでした。

は---編集を開始します -

が、私はその機能に私の強化型を渡すことができるようにしたい機能

def sendData(ex : ExternalType1) 

を考えると、目的の動作を追加します。

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

---エンド編集

私はこれらの線に沿って物事を行うことを試みたが、全く成功していなかった:

// 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 trait 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: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses self : T => t ^ defined class WithExtraData

scala> new WithExtraData[String]("hi", new ArrayByte) :13: error: class WithExtraData cannot be instantiated because it does not conform to its self-type WithExtraData[String] with String

がありますこれを達成する方法?

私はあなたが合理的に(少なくともマクロなし)を取得することができます最も近い ExternalType1を拡張するために、代わりに暗黙の型変換を持つことはないと思われる
+0

私はあなたが重要な要件を省略していることを推測していますを使用することです。このインスタンスをいくつかの外部ライブラリに渡すことができるように 'ExternalType1'を拡張しようとしていますか?それを戻して、' ExtraData'にキャストし、 'getExtraData'にキャストしますか?そうでない場合は、間違いなくサブクラス化から離れるべきです。 – drstevens

+0

はい、私はそれに似た何かをしようとしていますが、Kryoにはカスタムシリアライザがあります。 –

答えて

2

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 
} 

その後、あなたは、例えばすることができますExternalType1が必要な場合はいつでもWithExtraData[ExternalType1]を渡してください。

+0

私の理解では、それは "extraData"がリッピングされ、実際には渡されない原因になります。 –

+0

「切り取った」とはどういう意味なのでしょうか。私は単純に 'WithExtraData [A] =(A、Array [Byte]) 'をこの解決策としてさらに洗練されたものとして提案しようとしていましたが、実際に解決しようとしている問題は解決できません。 – drstevens

+0

はい、Tで動作する関数にWithExtraData [T]を引き渡すことができます。 –

0

あなたが正しいことを理解していれば、基本的に値で表される追加の型情報を使って型を充実させようとしますか?その場合、探しているコンセプトはDependent Types

という名前で呼ばれています。スカラはこの概念をネイティブにサポートしていません(たとえばIdrisなど)。しかし、近づくにはいくつかの回避策があります。

一つの例は、型崩れ

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

非常にクール! - しかし、私は余分なデータをインスタンス固有のものにしたいと思っています。 –

関連する問題