6

私は共通の基本特性の多くのクラスを持っています。これらのクラスのいずれかのインスタンスの新しいインスタンスを作成する必要がある関数がありますが、どちらが実行時にのみ認識されます。

このクラスをパラメーターとして渡し、Scalaで実行時にインスタンスを作成することは可能ですか?

答えが最善のアプローチであるかどうかさえわかりませんが、現在私が考えることができるのはそれだけです。

4

5 に答える 5

4

したがって、値を渡すことができます。

myFunc(classOf[myObj])

署名付きのメソッドに

def myFunc(clazz : AnyRef)={ ...

しかし、これは悪臭がします。ファクトリパターンの実装を検討している場合もあれば、ポリモーフィズムを使用して単純に次のことを実行する場合もあります。

myObj.myFunc

あなたの機能はどのクラスが関係しているかに基づいているからです。

于 2013-01-14T10:47:38.573 に答える
2

Javaの場合と同じ:

classOf[MyClass].newInstance // calls the constructor without parameters
classOf[MyClass].getConstructor(/* parameter types */).newInstance(/* parameters */)

クラスについてはJavadocを参照してください。

これはどのScalaバージョンでも機能します。Scala 2.10には、Scalaの概念を認識する新しいリフレクションライブラリがあります。

于 2013-01-14T11:05:01.600 に答える
1

テスト不可能なコードやランタイム例外に簡単につながる可能性があるため、リフレクションはできるだけ避けることをお勧めします。

ただし、次のようにそのクラスのビルダーを作成できます。

trait Builder[A]{
   def newItem:A
}

次に、適切なビルダーを関数に渡します

def myFunc[A](param1:B,builder:Builder[A])

また、暗黙を活用することもできます

def myFunc[A](param1:B)(implicit builder:Builder[A])

ユースケースをもう少し詳しく説明できるかもしれません。

于 2013-01-14T11:37:04.167 に答える
0

私は個人的に反省を避けます。

考えられるすべてのユースケースを事前に特定し、識別子を使用してそれらを分類できる場合:

trait SUPER

class A extends SUPER
class B extends SUPER
class C extends SUPER
class D extends SUPER

val idA = 'CLASS_A
val idB = 'CLASS_B
val idC = 'CLASS_C
val idD = 'CLASS_D

def build(selectedId: Symbol): SUPER = selectedId match {
  case 'CLASS_A => new A
  case 'CLASS_B => new B
  case 'CLASS_C => new C
  case 'CLASS_D => new D
}

そうでなければ、ビルダーを好むなら、私は@Edmondo1984のアドバイスに従うでしょう

于 2013-01-14T13:43:36.563 に答える
0

必要なものを取得するための最も「シームレスな」方法は、インスタンス化を行うメソッドを、コンテキストがバインドされた型パラメーターを持つものとして宣言することです。ClassManifest

def maker[T : ClassManifest](args...): T = ...

これにより、コンパイラは自動的にのインスタンスClassManifest[T]をmakerに渡します。呼び出し元は、インスタンス化する特定のクラスを指定するだけで済みます。

package rrs.scribble

import  scala.reflect.ClassManifest

object  Maker
{
  def maker[T : ClassManifest]: T = {
    val cmT = implicitly[ClassManifest[T]]
    val cT = cmT.runtimeClass
    cT.newInstance.asInstanceOf[T]
  }
}

これは、問題のクラスに引数なしのコンストラクターがある場合にのみ機能します。引数を使用してコンストラクターを呼び出すことができますが、それははるかに複雑です。JavaリフレクションAPIに精通している必要があります。

REPLでは:

scala> import rrs.scribble.Maker._
import rrs.scribble.Maker._

scala> class Argless
defined class Argless

scala> val s1 = maker[Argless]
s1: Argless = Argless@1512d075
于 2013-01-14T15:09:43.907 に答える