【问题标题】:Returning Options of Class types in Scala methods在 Scala 方法中返回类类型的选项
【发布时间】:2017-02-08 07:13:57
【问题描述】:

我正在为我正在写的东西处理 Class 类型而苦苦挣扎,答案可能涉及泛型,但我有点坚持正确的解决方案应该是什么。

我有一个 Scala 类 Vehicle,它有几个子类(CarBusTrainMotorcycle 等):

class Vehicle {
    ...
}

class Car extends Vehicle {
    ...
}

class Motorcycle extends Vehicle {
    ...
}

我现在正在尝试编写一个实用方法,可以将 String 映射到 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 方法返回一个instance,例如Car。如果提供“car”作为输入等,我希望它简单地返回Car 类。任何人都可以发现我出错的地方以及解决方案是什么。如果可能的话,我还想使用 Scala Options,因为 mapToVehicleType 方法当然可以返回 null

【问题讨论】:

  • 您能更具体地说明您要做什么吗?您的方法返回Vehicle 类型的对象,而不是类(类型)。类(类型)不是对象,不能返回,它们存在于平行宇宙中。

标签: scala generics introspection


【解决方案1】:

你为什么要上课?这确实是关键问题。如果您要使用反射动态实例化,您可能会考虑使用不同的模式。

反射是经常用来克服 Java 限制的东西之一(我将假设您来自 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

...但是我必须再次知道您要完成什么。我敢打赌有更好的模式。

【讨论】:

  • 感谢@john_omalley,我正在使用 Spark,它的一种 API 方法(特别是 StructType#add)需要您添加到的新列/字段的类类型作为参数结构。我正在编写一个帮助函数,它允许我将字符串值转换为它们正确的 Spark 等价物。所以是的,我确实需要类类型,而不是实例。
【解决方案2】:

Scala 提供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
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-17
    • 2011-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多