3

編集2:

以下のコードを使用して、ミックスインと型パラメーターの組み合わせを使用して、RomanNumeralsを使用した演習で必要な型安全性を達成することができました。本質的には、すべてをインポートした後、RomanNumerals書き込むことはできますが、タイプの不一致コンパイラエラーが発生します(ローマ数字の不正な組み合わせであるため)。今、私は、特性、ミックスイン、および型パラメーターを使用するこの方法が問題ないと見なされるのか、いわば言語を乱用しているのか疑問に思っています:)より単純でクリーンなもので同じ種類の型安全性を達成するより良い方法はありますかコード?L X V IL LX L X

object RomanNumerals {
  trait Numeral {
    def num:Int
  }
  trait NumeralI[N<:Numeral] extends Numeral
  trait NumeralV[N<:Numeral] extends NumeralI[N] {
    def I = new RomanNumeral[Numeral](1 + this.num) with Numeral
    def II = new RomanNumeral[Numeral](2 + this.num) with Numeral
    def III = new RomanNumeral[Numeral](3 + this.num) with Numeral
  }

  trait NumeralX[N<:Numeral] extends NumeralV[N] {
    def IV = new RomanNumeral[Numeral](4 
              + this.num) with Numeral
    def V = new RomanNumeral[NumeralI[Numeral]](5 
             + this.num) with NumeralV[NumeralI[Numeral]]
    def IX = new RomanNumeral[Numeral](9
              + this.num) with Numeral
  }

  trait NumeralL[N<:Numeral] extends NumeralX[N] {
    def X = new RomanNumeral[NumeralV[Numeral]](10
             + this.num) with NumeralX[NumeralV[Numeral]]
    def XX = new RomanNumeral[NumeralV[Numeral]](20 
              + this.num) with NumeralX[NumeralV[Numeral]]
    def XXX = new RomanNumeral[NumeralV[Numeral]](30 
               + this.num) with NumeralX[NumeralV[Numeral]]
  }

  class RomanNumeral[T <: Numeral](val num:Int) {
    override def toString = num toString
    def apply[N >: T <: Numeral](rn:NumeralI[N]) = 
      new RomanNumeral[Numeral](rn.num + num) with Numeral

    def apply[N >: T <: Numeral](rn:NumeralV[N]) = 
      new RomanNumeral[NumeralI[Numeral]](rn.num
       + num) with NumeralV[NumeralI[Numeral]]

    def apply[N >: T <: Numeral](rn:NumeralX[N]) = 
      new RomanNumeral[NumeralV[Numeral]](rn.num 
       + num) with NumeralX[NumeralV[Numeral]]

    def apply[N >: T <: Numeral](rn:NumeralL[N]) = 
      new RomanNumeral[NumeralX[Numeral]](rn.num 
       + num) with NumeralL[NumeralX[Numeral]]

  }

  val I = new RomanNumeral[NumeralI[Numeral]](1) with NumeralI[Numeral]
  val II = new RomanNumeral[NumeralI[Numeral]](2) with NumeralI[Numeral]
  val III = new RomanNumeral[NumeralI[Numeral]](3) with NumeralI[Numeral]
  val IV = new RomanNumeral[NumeralI[Numeral]](4) with NumeralI[Numeral]
  val V = new RomanNumeral[NumeralI[Numeral]](5) with NumeralV[NumeralV[Numeral]]
  val IX = new RomanNumeral[NumeralI[Numeral]](9) with NumeralI[Numeral]
  val X = new RomanNumeral[NumeralV[Numeral]](10) with NumeralX[NumeralX[Numeral]]
  val XX = new RomanNumeral[NumeralV[Numeral]](20) with NumeralX[NumeralX[Numeral]]
  val XXX = new RomanNumeral[NumeralV[Numeral]](30) with NumeralX[NumeralX[Numeral]]
  val XL = new RomanNumeral[NumeralV[Numeral]](40) with NumeralX[NumeralX[Numeral]]
  val L = new RomanNumeral[NumeralX[Numeral]](50) with NumeralL[NumeralL[Numeral]] 
}

編集:

ビクターの回答に基づくさらなる質問。わかりましたが、Bがトレイトになるように、typeパラメーターに上限と下限を追加するとどうなりますか?例えば

trait Bar
class Foo[T<:Bar](n:Int) {
  def apply[B >: T <: Bar](f:Foo[B]) = {
    new Foo[B](n + f.n) with B
  }
}

それともB、この場合でもクラスになることができますか?f引数も適用されることがわかっている場合はどうなりFoo[B] with Bますか?それを使用しBてリターンタイプとミックスインする方法はありますか?

以下の元の質問

Scalaでオブジェクトを作成するときに、型パラメーターとして取得するトレイトをミックスしたい:

class Foo(val num:Int) { 
  def withM[B](foo:Foo) = new Foo(foo.num) with B
}

これにより、コンパイルエラーが発生します。

error: class type required but B found
def withM[B](foo:Foo) = new Foo(foo.num) with B
                                              ^

私も試しました:

class Foo(val num:Int) { 
  def withM[B](foo:Foo) = new Foo(foo.num) with classOf[B]
}

しかし、それは機能しません:

error: not found: type classOf
def withM[B](foo:Foo) = new Foo(foo.num) with classOf[B]
                                              ^

これを回避する方法はありますか?withMの戻り型が次のようになるようFoo with Bに、Bはに渡される型パラメータです。withM

4

1 に答える 1

5

この種の機能は単純に不可能(または利用可能)です。また、特性(およびインターフェース)をミックスインすることのみが可能であり、コンパイラーが知る限り、型パラメーターはIntである可能性があります。

具体的な特性またはインターフェースタイプを次のように指定する必要があります。

trait T
class Foo
object Test {
  def apply = new Foo with T
}
于 2010-07-22T10:44:03.923 に答える