簡體   English   中英

scala。一些不能轉換為自定義對象

[英]scala.Some cannot be cast to custom object

我有下面的代碼。 我已經開始學習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 ,一旦從地圖中檢索到值就不必匹配。 如果不是這樣的理解是正確的,請讓我知道這里出了什么問題。

如果我們在scaladoc中查看scala.collection.mutable.Map.get() ,則方法簽名描述為:

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

該方法返回類型為Option的值; 如果嘗試將其ClassCastException為不相關的類型,則將獲得ClassCastException ,就像其他不兼容的類型一樣。 如果需要產品,則需要:

  • 檢查Option是否為空
  • 打開包裝在里面的產品

這是一種實現方式(無需更改其余代碼):

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)

嘗試productMap.get(name).get()。asInstanceOf [Product]或僅productMap(name).asInstanceOf [Product]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM