3

異なる型パラメーターを持つ型パラメーター化されたクラスのオブジェクトを返すメソッドを Scala で作成することは可能ですか? このようなもの:

class A[T]

def f(switch: Boolean): A = if(switch) new A[Int] else new A[String]

注意: 上記のコードは、問題の種類を示すための架空のものです。上記のコードは意味的に意味がありません。

戻り値の型 A がパラメーター化されていないため、上記のコードはコンパイルされません。

4

4 に答える 4

6

ペアリングをカプセル化する暗黙の引数を使用して、タイプセーフでそれを行うこともできます。

class TypeMapping[+A,B] {
  def newListB = List.empty[B]
}
trait Logical
object True extends Logical
object False extends Logical

implicit val mapFalseToInt = new TypeMapping[False.type,Int]
implicit val mapTrueToString = new TypeMapping[True.type,String]

def f[A <: Logical,B](switch: A)(implicit tmap: TypeMapping[A,B]) = tmap.newListB

scala> f(True)
res2: List[String] = List()

scala> f(False)
res3: List[Int] = List()

ブール値からカスタムTrueおよびFalse値に明示的にマップする必要があります。

(List例として、ターゲット クラスとして選択しました。任意のクラスを選択することも、もう少し作業を加えてジェネリックにすることもできます。)

(編集: oxbow_lakes が指摘しているように、可能なすべての戻り値を同じコード パスで表す必要がある場合、これだけではList[Int]それList[String]List[Any]できません。 、を使用する必要があります。私の解決策は、またはコンテキストでEitherのみ使用され、そこで型情報を維持できる単一の関数用です。)TrueFalse

于 2012-06-25T15:43:02.607 に答える
4

これを表現する 1 つの方法は、Either;を使用することです。

def f(switch: Boolean) = if (switch) Left(new A[Int]) else Right(newA[String])

もちろん、これは を返しますEither[A[Int], A[String]]。確かに (現時点では)P型パラメーターのサブセット (つまり、 orのみ ) を使用して、パラメーター化された型を返すメソッドを宣言することはできません。Int String

言語ceylonには共用体型があり、近い将来これらを scala に追加する意図があることを理解しています。その場合、メソッドを定義できます。

def f(switch: Boolean): A[Int|String] = ...
于 2012-06-25T15:43:40.923 に答える
0

まあ、あなたはそのようなことをすることができます。

scala> class A {
     |   type T
     | }
defined class A

scala> def f(b: Boolean): A = if(b) new A { type T = Int } else new A { type T = String }
f: (b: Boolean)A

しかし、これは無意味です。型はコンパイル時の情報であり、その情報はここで失われています。

于 2012-06-25T15:43:35.273 に答える
-1

「架空のコード」への最小限の変更はどうですか?[_]「架空の」リターンタイプの後に追加するだけで、コードはコンパイルされます。

class A[T]
def f(switch: Boolean):A[_] = if(switch) new A[Int] else new A[String]

A[_]と同じではないことは注目に値しA[Any]ます。A[T]コードをコンパイルするために共変を定義する必要はありません。残念ながら、タイプに関する情報は失われます。

于 2012-06-25T15:37:17.247 に答える