【问题标题】:Is it possible to convert string to type in Scala reflection?是否可以将字符串转换为 Scala 反射中的类型?
【发布时间】:2018-05-24 11:15:47
【问题描述】:

我想将字符串转换为scala中的类型。以以下两种情况为例:

case class Product(id: String, title: String, description: String)
type aType = Product
client.getProduct[aType](id, "/products").map { x => println(s"Retrieved Product with id '$id': $x") } // Working 
// Retrieved Product with id 'test_id': Some(Product(test_id,MyTitle,The text of my Product))

case class Store(id: String, title: String, Address: String)
type aType = Store
client.getStore[aType](id, "/stores").map { x => println(s"Retrieved Store with id '$id': $x") } // working
// Retrieved Store with id 'test_id': Some(Store(test_id, Store Name,The address of my Store))

我想让这个代码对任何请求都通用,因为已经定义了案例类。例如

case class Product(id: String, title: String, description: String)
case class Store(id: String, title: String, Address: String)
case class API_Detail(Name: String, CaseClassName: String, Api_Url:String)
var API_List = List[API_DS]()

val request_type = "Product" // or "Store"
val id = "test_id"

val API_List_Item = API_List.filter(_.Name == request_type)
// Want to do like this...
type aType = API_List_Item.CaseClassName.toType /**/
val RequestURL = API_List_Item.Api_Url
/* Interested to know how to convert string to type. To my knowledge
   some form of reflection will be implemented. */

client.getRespone[aType](id, RequestURL).map { x => println(s"Retrieved $request_type with id '$id': $x") } // Working 
// Retrieved Product with id 'test_id': Some(Product(test_id,MyTitle,The text of my Product))

【问题讨论】:

  • 这里的产品是案例类。案例类产品(id:字符串,标题:字符串,描述:字符串)
  • 我不认为这是可能的,但向我们展示更多的背景,我们也许能够解决它。例如应该如何进一步使用response?预计谁会调用此代码?您是否希望能够访问response.id(和其他字段)?如果是这样,编译器如何确定(在编译时)response 的类型是 Product,而您只想在运行时提供实际类型?
  • 感谢您的回复。我试图详细说明我的要求,但由于 255 个字符的限制而失败。我在以下链接中创建了一个新问题。请看它并帮助我。提前致谢。 stackoverflow.com/questions/47746027/…
  • Waqas,你,作为问题的作者。可以对其进行编辑以提供更多详细信息。您不必在每条有价值的评论之后都创建一个新问题:)。
  • 谢谢 SergGr。我已经更新了我的要求。

标签: string scala reflection types


【解决方案1】:

感谢您邀请我参加此主题。也许您可以通过使用模式匹配来保持解决方案足够简单。使用隐式类的另一种解决方案也是有效的。

val requestUrl = "/products"
requestUrl match {
 case "/products" => Products(...)
 case "/store" => Store(...)
 case _ => UnknownType
}

有关模式匹配的其他示例,请参阅我的教程allaboutscala.com

【讨论】:

  • 这里的问题是match语句的返回类型。问题中定义的ProductStore 是不相关的类型,因此语句返回类型基本上没有意义。您必须对其进行强制转换或重新匹配它,才能从中获得有用的 ProductStore
【解决方案2】:

我正在扩展我之前关于模式匹配的答案。如果我们有Polymorphic Function 并且我正在使用Type Classes,则无需重新匹配模式。我还在 allaboutscala.com 上提供了关于类型类构建块的详细教程:一般的特征、隐式和函数。

您需要扩展 getResponse(...) 来为您的具体类型构建和填充字段。

  case class Product(id: String, title: String, description: String)
  case class Store(id: String, title: String, address: String)

  trait Client[T] {
    def getResponse(s: String): Option[T]
  }

  object Client {
    implicit val productClient: Client[Product] = new Client[Product] {
      override def getResponse(s: String): Option[Product] = s match {
        case "/product" => Some(Product("id", "title", "description"))
        case _ => None
     }
  }

   implicit val storeClient: Client[Store] = new Client[Store] {
     override def getResponse(s: String): Option[Store] = s match {
       case "/store" => Some(Store("id", "title", "address"))
       case _ => None
     }
  }

  def apply[T : Client](s: String): Option[T] = 
    implicitly[Client[T]].getResponse(s)
  }

val product: Option[Product] = Client[Product]("/product")
val store: Option[Store] = Client[Store]("/store")

【讨论】:

    猜你喜欢
    • 2011-12-29
    • 2017-07-02
    • 2013-12-11
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 2017-09-12
    • 2012-10-28
    • 1970-01-01
    相关资源
    最近更新 更多