java - scala.Some 无法转换为自定义对象

标签 java scala

我有以下代码。我已经开始学习 scala,所以可能会有更好的方法来完成这些事情,但我想学习它的每一点。如果代码看起来如此幼稚,请耐心等待。

  class ColaProduct() extends Product{
    override def productName = "Cola"
    override def productDetails = "Chilled Cola"
    override def toString(): String = super.toString()
  }

  class MilkProduct() extends Product{
    override def productName = "Milk"
    override def productDetails = "Healthy Milk"
    override def toString(): String = super.toString()
  }

  trait Machine {
    private val productMap = scala.collection.mutable.Map[String, Product]()
    def addProduct(product: Product): Unit ={
      productMap += product.productName.toString -> product
    }
    def checkAvl(name :String): Product ={
      if(productMap contains(name)){
        return productMap.get(name).asInstanceOf[Product]
      } else null
    }
    def process(name :String)
  }

  class VendingMachineImpl() extends Machine{
    override def process(name : String): Unit ={
      val product = checkAvl(name)
      if(null !=product){
        print("Got you :"+product.toString())
      }
    }
  }

  trait Product {

    private val defaultString: String = "Default"
    def productName = defaultString
    def productDetails = defaultString

    override def toString(): String = {
      return productName + " || " + productDetails
    }
  }

  def main(args : Array[String]): Unit ={
    val vendingMachineImpl = new VendingMachineImpl()
    vendingMachineImpl.addProduct(new ColaProduct)
    vendingMachineImpl.addProduct(new MilkProduct)

    vendingMachineImpl.process("Cola")
  }

异常:

Exception in thread "main" java.lang.ClassCastException: scala.Some cannot be cast to Product
    at vendingMachine$Machine$class.checkAvl(vendingMachine.scala:27)
    at vendingMachine$vendingMachineImpl.checkAvl(vendingMachine.scala:33)
    at vendingMachine$vendingMachineImpl.process(vendingMachine.scala:35)
    at vendingMachine$.main(vendingMachine.scala:47)

我相信,一旦我定义了具有指定类型的map,一旦从 map 中检索值,我就不必进行匹配。这种理解是否正确,如果不正确,请让我知道这里出了什么问题。

最佳答案

如果我们查看 scaladoc 中的 scala.collection.mutable.Map.get() ,方法签名描述为:

 abstract def get(key: A): Option[B]

该方法返回一个Option类型的值;如果您尝试将其转换为某种不相关的类型,您将得到一个 ClassCastException 异常,就像任何其他不兼容的类型一样。如果您想要产品,您需要:

  • 检查选项是否不为空
  • 打开里面的产品包装

这是一种实现方法(无需更改其余代码):

trait Machine {
  // Notes:
  // - no need to use 'return' keyword
  // - It's good practice in Scala not to return null: use Option for optional values
  def checkAvl(name :String): Option[Product] =
    productMap.get(name)
}

class VendingMachineImpl() extends Machine{
  override def process(name : String): Unit ={
    val product = checkAvl(name)
    // Think of Option as a collection containing 0 or 1 element: you can use
    // foreach, map, etc.
    // Also, string interpolation (with the s"" syntax) is cool. :-)
    product.foreach(print(p => s"Got you : $p"))
  }
}
<小时/>

编辑: 此外,在 Scala 中,由于模式匹配,您通常可以避免显式强制转换。例如,如果您想从 Option[Product] 中显式解开 Product,您可以使用:

val opt: Option[Product] = ???
opt match {
  // type-safe cast to type Some and deconstruction of the object (we get out the value
  // wich was originally passed to the Some constructor) :
  case Some(product) => print(s"Got you : $product")
  // type-safe cast to type None :
  case None => // do nothing
}
<小时/>

编辑2: 您还可以查看其他两种从 Map 检索值的方法,具体取决于您要执行的操作:

val map: Map[String, String] = Map("k1" -> "v1", "k2" -> "v2")

// getOrElse (using a default value)
map.getOrElse("k1", "default") // returns "v1"
map.getOrElse("foobar", "default") // returns "default"

// apply (implementation-dependent, but fails fast by default)
map("k1") // returns "v1"
map("foobar") // throws a NoSuchElementException (it can be different for other Map
              // implementations, but it's the default behavior)

关于java - scala.Some 无法转换为自定义对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37180088/

相关文章:

java - 无法比较类型错误 : Object and int in Telegram

java - 如何创建出现在程序最顶部的 Swing 菜单栏?

scala - 字段中的空值会生成 MatchError

java - 通过 csv 文件 Java 存储值的最佳结构

java - Eclipse -> Run as -> Run on server - 如何让它与 JBoss 一起工作?

java - 如何在java中按位移动二进制字符串?

scala - 禁用 Scala REPL 中的弃用警告

java - Scala:将 java 接口(interface)移植到 scala

java - 使用 Java 中的字段继承 Scala 特征

scala - 了解 UID 在 Spark MLLib Transformer 中的作用