在 Scala 方法中返回 Class 类型的选项
Returning Options of Class types in Scala methods
我正在努力处理我正在写的东西的 Class
类型,答案可能涉及泛型,但我对正确的解决方案应该是什么感到困惑。
我有一个 Scala class Vehicle
有几个 child classes (Car
, Bus
, Train
, Motorcycle
, 等等):
class Vehicle {
...
}
class Car extends Vehicle {
...
}
class Motorcycle extends Vehicle {
...
}
我现在正在尝试编写一个实用方法,可以将字符串映射到 Vehicle
subclass(即 Class
,不是那个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
}
}
问题是我 confusing/blurring 类型与实例。我不希望 mapToVehicleType
方法到 return 一个 实例 ,比方说,Car
。我希望它简单地 return Car
class 如果“car
”作为输入提供,等等。任何人都可以发现我在哪里出错以及解决方案是什么.如果可能的话,我也想使用 Scala Options
,因为 mapToVehicleType
方法当然可以 return null
.
Scala 提供 classOf[T]
来获取 class 类型的 class。例如:classOf[Car]
returns 类型的实例 Class[Car]
.
为了映射到适当的 class 类型,您可以使用模式匹配将类型从提供的字符串映射到 Option
:
def mapToVehicleType(vehicleType: String): Option[Class[_ <: Vehicle]] = {
vehicleType match {
case "car" => Some(classOf[Car])
case "motorcycle" => Some(classOf[Motorcycle])
case _ => None
}
}
为什么要 class?这真的是关键问题。如果您要使用反射动态实例化,您可能会考虑不同的模式。
反射是经常用来克服 Java 限制的事物之一(我假设您来自 Java)。但是 Scala 中通常有更好的模式。
您可以 return class(例如 classOf[Car]),但请考虑更好的算法。
假设,为了便于讨论,您将 returnclass 作为 "factory"。我不确定这是最好的模式,但你可以考虑这样的事情而不是反思:
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
...但是我必须再次知道您想要完成什么。我敢打赌有更好的模式。
我正在努力处理我正在写的东西的 Class
类型,答案可能涉及泛型,但我对正确的解决方案应该是什么感到困惑。
我有一个 Scala class Vehicle
有几个 child classes (Car
, Bus
, Train
, Motorcycle
, 等等):
class Vehicle {
...
}
class Car extends Vehicle {
...
}
class Motorcycle extends Vehicle {
...
}
我现在正在尝试编写一个实用方法,可以将字符串映射到 Vehicle
subclass(即 Class
,不是那个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
}
}
问题是我 confusing/blurring 类型与实例。我不希望 mapToVehicleType
方法到 return 一个 实例 ,比方说,Car
。我希望它简单地 return Car
class 如果“car
”作为输入提供,等等。任何人都可以发现我在哪里出错以及解决方案是什么.如果可能的话,我也想使用 Scala Options
,因为 mapToVehicleType
方法当然可以 return null
.
Scala 提供 classOf[T]
来获取 class 类型的 class。例如:classOf[Car]
returns 类型的实例 Class[Car]
.
为了映射到适当的 class 类型,您可以使用模式匹配将类型从提供的字符串映射到 Option
:
def mapToVehicleType(vehicleType: String): Option[Class[_ <: Vehicle]] = {
vehicleType match {
case "car" => Some(classOf[Car])
case "motorcycle" => Some(classOf[Motorcycle])
case _ => None
}
}
为什么要 class?这真的是关键问题。如果您要使用反射动态实例化,您可能会考虑不同的模式。
反射是经常用来克服 Java 限制的事物之一(我假设您来自 Java)。但是 Scala 中通常有更好的模式。
您可以 return class(例如 classOf[Car]),但请考虑更好的算法。
假设,为了便于讨论,您将 returnclass 作为 "factory"。我不确定这是最好的模式,但你可以考虑这样的事情而不是反思:
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
...但是我必须再次知道您想要完成什么。我敢打赌有更好的模式。