1

ジェネリック型のコンストラクターを呼び出したいのですが、引数Tが 1 つだけの特定のコンストラクターも必要です。Int

 class Class1[T] {
   def method1(i: Int) = {
     val instance = new T(i)  //ops!
     i
   }
 }

この要件を指定するにはどうすればよいですか?

更新:このようなものを使用することは、どの程度許容されますか(柔軟性など)?それがテンプレートメソッドのパターンです。

 abstract class Class1[T] {

   def creator: Int => T

   def method1(i: Int) = {
     val instance = creator(i)  //seems ok
     i
   }
 }
4

2 に答える 2

1

ジェネリック クラスまたはジェネリック トレイトを作成する場合、そのクラスは、パラメーター化する可能性のある実際のクラスのメソッドへの特別なアクセスを取得しません。あなたが言う時

class Class1[T]

あなたが言っています

  1. これは、未指定の型 T で動作するクラスです。
  2. そのメソッドのほとんどは、型 T のインスタンスをパラメーターとして受け取るか、T を返します。
  3. 型パラメーターに付加されたバリアンス アノテーションまたは型境界は、それが Class1 のいずれかのメソッドのパラメーターとして表示されるたびに適用されます。
  4. タイプ「Class1」などはありませんが、タイプ「Class1[something]」の任意の数の派生クラスが存在する可能性があります

それで全部です。Scala は T が何であるかを認識しないため、Class1 内から T に特別にアクセスすることはできません。Class1 が T のフィールドとメソッドにアクセスできるようにする場合は、Class1 を拡張または混在させる必要があります。

T のメソッドに (リフレクションを使用せずに) アクセスしたい場合は、T 型のパラメーターを受け入れる Class1 のメソッドの 1 つからのみアクセスできます。渡される実際のオブジェクト。

(これはリフレクションで回避できますが、これはランタイム ソリューションであり、タイプセーフではありません)。

元のコード スニペットで何をしようとしているのかを見てください...

  1. Class1 を任意の型でパラメータ化できることを指定しました。
  2. 単一の Int パラメータを取るコンストラクタで T を呼び出したい

しかし、T がそのようなコンストラクターを持つことを Scala コンパイラーに約束するために、あなたは何をしましたか? 何もありません。では、コンパイラはこれをどのように信頼できるのでしょうか? まあ、それはできません。

T がそのようなコンストラクターを持つクラスのサブクラスであることを要求する型の上限を追加したとしても、それは役に立ちません。T は、単純なコンストラクターにコールバックする、より複雑なコンストラクターを持つサブクラスである可能性があります。したがって、 Class1 が定義されている時点で、コンパイラはその単純な方法で T を構築することの安全性について確信を持つことができません。そのため、その呼び出しはタイプセーフではありません。

クラスベースの OO は、エーテルから未知の型を呼び出すことではありません。シルクハットの形をしたクラスローダーに手を突っ込んで驚きを引き出すことはできません。特定のタイプを知らなくても、いくつかの一般的なタイプの任意の作成済みインスタンスを処理できます。これらのオブジェクトが作成される時点では、あいまいさはまったくありません。

于 2013-09-08T21:45:58.430 に答える