5

次の Scala 宣言は問題ありません。

trait Base[B <: Base[B,M,ID], M <: Meta[B,M,ID], ID <: Comparable[ID]] {
    // ...
}

trait Meta[B <: Base[B,M,ID], M <: Meta[B,M,ID], ID <: Comparable[ID]] extends Ordered[Meta[_,_,_]] {
    // ...
}

trait BaseWithID[B <: BaseWithID[B,M,ID], M <: Meta[B,M,ID], ID <: Comparable[ID]] extends Base[B,M,ID] with Ordered[B] {
    // ...
}


trait BaseWithIntID[B <: BaseWithIntID[B,M,ID], M <: MetaWithIntID[B,M,ID], ID <: Comparable[ID]] extends BaseWithID[B,M,ID] {
    // ...
}

trait MetaWithIntID[B <: BaseWithIntID[B,M,ID], M <: MetaWithIntID[B,M,ID], ID <: Comparable[ID]] extends Meta[B,M,ID] {
    // ...
}

ただし、次の 2 つはそうではありません。

trait BaseWithIntID[B <: BaseWithIntID[B,M], M <: MetaWithIntID[B,M]] extends BaseWithID[B,M,Int] {
    // ...
}

trait MetaWithIntID[B <: BaseWithIntID[B,M], M <: MetaWithIntID[B,M]] extends Meta[B,M,Int] {
    // ...
}

違いは、BaseWithIntID と MetaWithIntID の ID 型パラメーターを削除し、それぞれの基本特性で明示的に Int を指定したことです。しかし、これはコンパイルされないので、Int は Scala で Comparable ではないということですか? もしそうなら、私は何を間違っていますか?Comparable の代わりに Ordered を試しましたが、違いはありませんでした。

私はEclipseを使用していますが、いつものように、エラーメッセージは役に立ちません:

type arguments [B,M,Int] do not conform to trait BaseWithID's type parameter bounds [B <: BaseWithID[B,M,ID],M <: Meta[B,M,ID],ID <: java.lang.Comparable[ID]]

何かが間違っていると言っているだけで、どの型パラメーターが間違っているのか、そしてその理由はわかりません。この質問を見て、代わりに「ID <% Comparable[ID]」を試すことができると思いましたが、それは特性宣言では合法ではありません。

実際には、これも機能しません (同じエラー メッセージが表示されます)。

trait TestBase extends BaseWithID[TestBase,TestMeta,Int]

trait TestMeta extends Meta[TestBase,TestMeta,Int]
4

2 に答える 2

10

intInt は、実際には javaではなくjava として実装されているため、確かに scala では比較できませんjava.lang.Integer。それが不可能だったかどうかはわかりません。C# struct(値型) はインターフェイスを実装している可能性がありますが、ここでは行われません。

あなたが通常行うことはOrdering、ID タイプの暗黙的なスコープで利用可能ながあると言うことID : Orderingです。

簡単な例:

import Ordering.Implicits._
def max[A : Ordering](x: A, y: A) : A = if (x > y) then x else y

これは、 Ordering ( a と同じものjava.util.Comparator) を関数に渡すことになります。確かに宣言は

def max[A : Ordering](x: A, y: A)

に変換します

def max[A](x: A, y: A)(implicit ev: Ordering[A])

ev新しい名前です。A : Ordering がコードのようにメソッド定義ではなくクラスに表示される場合、コンストラクターへの暗黙的なパラメーターに変換され、必要に応じてフィールドに保持され、クラスの暗黙的なスコープで使用できるようになります。これは、あなたのものではなく、Comparable を実装していないクラスで使用される可能性があるため、 A を強制的にComparable( in scala)にするよりも柔軟です。Orderedデフォルトのものを逆にすることによってのみ、同じクラスの異なるオーダーリングから選択することもできます:まさにそれを行うdef reverse : Orderingメソッドがあります。Ordering

悪い面としては、VM が比較メソッドの呼び出しをインライン化できる可能性は低いですが、ジェネリックのインターフェイス メソッドを使用する場合もそうではありませんでした。

Comparable<T>Javaで実装される型 は、 object 内の暗黙的なメソッド ()Orderingによって暗黙的なスコープを自動的に取得します。javaは( )に変換することもできます。orderedOrderingComparator<T>OrderingOrdering.comparatorToOrdering

Ordering.Implicits._ をインポートすると、 anが暗黙のスコープx > yにある場合に、適切な構文が可能になります。Ordering[A]

于 2011-07-24T10:56:20.610 に答える
0

「Int は Scala では Comparable ではないということですか?」に対する答え。Int を java.lang.Integer に置き換えると、エラーなしでコンパイルされるため、明らかに YES です。問題は、ID にアクセスするたびにラッパー オブジェクトを作成しなければならないことです。これは頻繁に発生するため、費用がかかります。

ID が Comparable/Ordered であることを指定して、BaseWithID 自体を順序付けできるようにし、比較可能な ID を使用して明示的に比較メソッドを定義したいと考えました。

現時点での解決策は、ID が順序付けられていることを指定せず、トレイトで 1 回実装するのではなく、具象クラスに比較自体を実装させることです。誰かがより良い解決策を持っていますか?

于 2011-07-24T10:46:11.657 に答える