2016-09-29 3 views
1

私が書いているものに対してClass型を扱うのには苦労しています。答えにはジェネリックスが含まれるかもしれませんが、正しい解決策が何であるべきかについては固執しています。スカラメソッドのクラス型のオプションを返す

私はいくつかの子クラス(CarBusTrainMotorcycle、など)を持つScalaのクラスVehicleを持っている:

class Vehicle { 
    ... 
} 

class Car extends Vehicle { 
    ... 
} 

class Motorcycle extends Vehicle { 
    ... 
} 

私が今までの文字列をマッピングすることができるユーティリティメソッドを記述しようとしていますVehicleサブクラス(すなわち、それはClassある、ないそのクラスのインスタンス):

object VehicleUtils { 
    def mapToVehicleType(vehicleType : String) : Vehicle = { 
     var vType : Vehicle = null 
     if(vehicleType == "car") { 
      vType = Car 
     } else if(vehicleType == "motorcycle") { 
      vtype = Motorcycle 
     } else if(...) { 
      ...etc. 
     } 

     vType 
    } 
} 

問題は、タイプとインスタンスを混乱させたり混乱させたりすることです。 mapToVehicleTypeメソッドがのインスタンス(たとえば、Car)を返すことは望ましくありません。入力として「car」が提供されている場合は、単にCarクラスを返すようにしたいと思います。可能であれば、メソッドがnullを返すことができるので、Scala Optionsも使用したいと思います。

+0

あなたは何をしようとしているのか具体的になることができますか?あなたのメソッドはクラス(型)ではなく、Vehicle型のオブジェクトを返します。クラス(型)はオブジェクトではなく、返すことはできません。それらはパラレルユニバースに存在します。 –

答えて

2

スカラは、クラスのクラスタイプを取得するためにclassOf[T]を提供します。たとえば、classOf[Car]は、タイプClass[Car]のインスタンスを返します。

適切なクラス型へのマッピングのために、あなたはOptionに提供した文字列から型をマップするためにパターンマッチングを使用することができます。

def mapToVehicleType(vehicleType: String): Option[Class[_ <: Vehicle]] = { 
    vehicleType match { 
     case "car"  => Some(classOf[Car]) 
     case "motorcycle" => Some(classOf[Motorcycle]) 
     case _   => None 
    } 
} 
1

は、なぜあなたは、クラスをしたいですか?それが本当に重要な質問です。リフレクションを使用して動的にインスタンス化する場合は、別のパターンを考慮する必要があります。

反射は、Javaの限界を克服するためによく使用されるものの1つです(私はあなたがJavaから来ていると仮定します)。しかし、Scalaには通常、より良いパターンがあります。

クラスを返すことはできますが(classOf [Car]など)、より良いアルゴリズムを検討してください。

たとえば、引数として、クラスを「ファクトリ」として返すとします。私はそれが最良のパターンであるかどうかはわかりませんが、反射の代わりに次のようなものを考えてみてください:

object GetVehicleCreator { 
    def apply(vehicleType: String): Option[() => Vehicle] = vehicleType match { 
    case "car" => 
     Some(() => new Car) 
    case "motorcycle" => 
     Some(() => new Motorcycle) 
    case _ => 
     None 
    } 
} 

"utils"オブジェクトではないことに注意してください。 "utils"の使用はScala IMOのアンチパターンです(正直なところ私はそれもJavaのほうが嫌いです)。関数を作成するだけです。 applyメソッドを持つものはすべて関数です。使用する:

val vehicleOption: Option[Vehicle] = for { 
    fn <- GetVehicleFactory("car") 
    vehicle <- fn() 
} yield vehicle 

...でも、私はあなたが達成しようとしていることを知っている必要があります。私はそれのためのよりよいパターンがあると確信しています。

+0

ありがとう@john_omalley、私はSparkを使用しています。そのAPIメソッドの1つ(特に 'StructType#add')は、構造体に追加する新しい列/フィールドのクラス型を引数として必要とします。私は文字列の値を適切なSparkの等価物に変換するためのヘルパー関数を書いています。だから**はい**、私はクラスの型ではなく、インスタンスが必要です。 – smeeb

関連する問題