对象的Scala隐式转换 [英] Scala implicit conversion for object

查看:120
本文介绍了对象的Scala隐式转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下代码段:

import scala.language.implicitConversions

sealed trait Command {
  val typeName: String
}

object Command {

  implicit def command2String(implicit c: Command): String =
    c.typeName

}

case object SendMessageCommand extends Command {
  override val typeName: String = "send_message"
}

我想在没有显式转换的情况下将StringCommand后代进行比较.例如:

I would like to compare String with Command descendants without explicit conversion. For example:

"sendMessage" == SendMessageCommand

问题1:在Scala中可以吗?

Q1: Is it possible in Scala?

Q2:我可以定义泛型隐式转换来将诸如String之类的已知类型转换为超类类型(在我的情况下为Command)吗?

Q2: Can I define generic implicit conversion that will convert known type such as String to super class types (like Command in my case)?

例如:

implicit def string2Command(implicit s: String): Command = {
  case "send_message" => SendMessageCommand
  case _ => // some error thrown
}

P.S.我知道这不是惯用的Scala,但是找到正确的方法真是太棒了.

P.S. I know that it is not idiomatic Scala, but it would be awesome to find out the right way.

推荐答案

是的,有可能,但==不能,因为Scala仅在以下情况下支持隐式转换:转换为期望的类型,即选择项的接收者以及隐式参数,因此隐式不适用于比较情况.相反,您必须在Command trait中创建一个comparison method,如下所示.

Yes, its possible, but not with == because Scala support implicit conversion for these cases only: conversions to an expected type, conversions of the receiver of a selection, and implicit parameters and hence implicit is not applicable for comparison case. Instead, you have to create a comparison method in Command trait as below.

  sealed trait Command {
    val typeName: String
    def isEqual(c: Command) = c.typeName == this.typeName
  }

  object SendMessageCommand extends Command {
    override val typeName: String = "send_message"
  }

  implicit def stringToCommand(s: String) = new Command {override val typeName: String = s}
  implicit def commandToString(c: Command) = c.typeName

  val strToCmdCompare = "send_message" isEqual SendMessageCommand
  val cmdToStrCompare = SendMessageCommand isEqual "send_message"

  println(strToCmdCompare)    //print true
  println(cmdToStrCompare)    //print true

现在,要问您的第二个问题,是的,可以定义一个通用的隐式转换,以将任何给定类型转换为另一个类型实例.但是,据我了解您的情况,您具有Commands对象的列表,并且您希望这些对象中的特定命令具有给定的字符串名称.为此,您必须拥有这些实例列表.

Now, coming to your second question, yes its possible to define a generic implicit conversion to convert any given type into another type instance. However, as I am understanding your situation, you have list of objects of Commands, and you want particular command within those objects for given string name. For this, you must have hold of those list of instance.

  sealed trait Command {
    val typeName: String
    //This is required for implicit conversion.
    override def toString: String = typeName
  }

  object SendMessageCommand extends Command {
    override val typeName: String = "send_message"
  }
  object AddMessageCommand extends Command {
    override val typeName: String = "add_message"
  }
  object UpdateMessageCommand extends Command {
    override val typeName: String = "update_message"
  }
  object DeleteMessageCommand extends Command {
    override val typeName: String = "delete_message"
  }

  //List of commands.
  implicit val cmds: List[Command] = List(SendMessageCommand, AddMessageCommand, UpdateMessageCommand, DeleteMessageCommand)

  //Convert given type T into type U.
  implicit def convert[T, U](s: T)(implicit list: List[U]): Option[U] = {
    list.find(_.toString == s.toString)
  }
  val res: Option[Command] = "add_message"
  println((res.getOrElse(null) == AddMessageCommand)) //print true

注意:由于我正在通过转换将两个类型实例转换为string来比较两个类型实例,因此对于此用例,我必须在Command中重写toString方法.如果T不是字符串,也可能需要这样做.此外,您可以根据需要在convert method中实现自己的逻辑,而不必与toString转换进行比较.

Note: as I am comparing two type instance in conversion by converting them into string, I have to override toString method in Command for this use case. You may need to do so for type T as well if it is not string. Furthermore, you can implement you own logic in convert method as per required instead of comparing with toString conversion.

这篇关于对象的Scala隐式转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆