2011-01-05 10 views
3

型パラメータを使用する代わりに抽象型を使用して以下のコードを表現する方法を理解しようとしています。抽象型との型のvalメンバーのスカラの比較

trait Key extends Ordered[Key] { 
    type K 
    val key:K 
} 

case class DoubleKey(val key:Double) extends Key { 
    type K = Double 
    def compare(that:Key):Int = this.key compare that.key.asInstanceOf[K] 
} 

をしかし、私は型Kへの明示的なキャストに満足していないよ:that.key.asInstanceOf[K]次のように

trait Key[T] extends Ordered[Key[T]] { 
    val key:T 
} 

case class DoubleKey(key:Double) extends Key[Double] { 
    def compare(that:Key[Double]):Int = this.key compare that.key 
} 

私の現在のバージョンが見えます。抽象型を使用して抽象メンバの順序付けを行う方法が他にもありますか?

私もthat:Keyの種類がDoubleであることを確認しようとしています:

def compare(that:Key { type K = Double }):Int = this.key compare that.key

が、比較すると思いますdoesntのコンパイラが定義されているので、これも失敗します。また、K(例えばtype K <: Ordered[K])を制限することによってcompareを形質キーに移動できる解決策がありますか?

+0

私は完全にここに発注を避けるためにお勧め、との思いOrdering [DoubleKey]を伴う暗黙のオブジェクトを提供します。それは物事をはるかに簡単になります... – Landei

答えて

1

キーからタイプパラメータを削除し、キーを安全に順序付けることができる唯一の方法は、キータイプの順序キータイプからの暗黙の変換を定義することです。これにより、compareメソッドを除外することも簡単になります。

trait Key { type K ; val key : K } 

object Key { 
    type PKey[KK] = Key { type K = KK } 
    implicit def keyIsOrdered[K <% Ordered[K]](lhs : PKey[K]) = new Ordered[PKey[K]] { 
    def compare(rhs : PKey[K]) = lhs.key compare rhs.key 
    } 
} 

case class DoubleKey(val key : Double) extends Key { type K = Double } 
case class StringKey(val key : String) extends Key { type K = String } 

サンプルREPLセッション(NB。トレイト/ REPLがコンパニオンとしてそれらを見ていることを確認するためにダミーのオブジェクトのキーオブジェクトをラップする)、

scala> DoubleKey(23) < DoubleKey(34) 
res3: Boolean = true 

scala> StringKey("foo") < StringKey("bar") 
res4: Boolean = false 

scala> StringKey("foo") < DoubleKey(23) 
<console>:14: error: could not find implicit value for parameter ord: scala.math.Ordering[ScalaObject] 
     StringKey("foo") < DoubleKey(23) 
4

DoubleKeyと言って、少なくとも1つのタイプパラメータが必要だと思います。StringKeyは比較できません。それはあなたがクラスのキャスト例外を得ることができ、あなたの現在の設計ではDoubleKey(1.0) < StringKey("foo")

を書くために意味がありません。ここで

case class StringKey(val key:String) extends Key { 
    type K = String 
    def compare(that:Key):Int = this.key compare that.key.asInstanceOf[K] 
} 

StringKey("b") < DoubleKey(1.0) // ClassCastException 

は、コンパイル時に制約を強制し、また、比較の定義を引っ張ってくるの定義でありますDouble又はStringが注文のサブタイプではなく、利用可能な暗黙の変換が存在するように、私は、結合したビューを使用

abstract class Key[K <% Ordered[K]] extends Ordered[Key[K]] { 
    val key:K 
    def compare(that:Key[K]): Int = key compare that.key 
} 

case class DoubleKey(key:Double) extends Key[Double] 
case class StringKey(key:String) extends Key[String] 

StringKey("b") < DoubleKey(1.0) // won't compile 

注:ベース部材に。

+0

この返答いただきありがとうございます!それは "受け入れられた"ものよりも簡潔です。 – Malcolm

関連する問題