【问题标题】:Scala : Define implicit functions in an object or in a classScala:在对象或类中定义隐式函数
【发布时间】:2016-07-29 22:08:27
【问题描述】:

我正在学习 Play2 框架并开始使用隐式函数。我正在将一些 Position 对象转换为 Json :

implicit val locationWrites = new Writes[Position] {
    def writes(position: Position) = Json.obj(
      "lat" -> position.lat,
      "lon" -> position.lon
    )
}

我应该这样做:

object JsonConversion {
  implicit val locationWrites = new Writes[Position] {
    def writes(position: Position) = Json.obj(
      "lat" -> position.lat,
      "lon" -> position.lon
    )
  }
}

或者我应该这样做:

class JsonConversion {
  implicit val locationWrites = new Writes[Position] {
    def writes(position: Position) = Json.obj(
      "lat" -> position.lat,
      "lon" -> position.lon
    )
  }
}

然后导入这个classobject 将使用这些隐式函数。

在这些隐式函数的实例和可扩展性方面的根本区别是什么,例如,如果它们要以并发方式调用?

【问题讨论】:

  • 你打算如何“导入一个类”?试试看...

标签: scala concurrency playframework-2.0 instance implicit


【解决方案1】:

也不是。有一种更简洁的方法可以将您的所有域放在一起,而人们通常会忘记这一点。 您可以在伴生对象中添加隐含

你应该把它们放在这里:

class Position { ... }
object Position {
  implicit val positionWrites = new Writes[Position] {
    def writes(position: Position) = Json.obj(
    "lat" -> position.lat,
    "lon" -> position.lon
    )
  }
}

默认情况下,隐式解析会查看伴随对象。这可以防止域分散,并且不会出现充满 JSON 格式的奇怪文件。您可以将事物耦合在正确的位置,并且如果您更新类,很容易知道哪些地方需要更改。

附带说明,Play 使用一些有趣的宏生成更高级的 JSON 格式。您可以使用Json.format[Type]Json.writes[Type] 或仅使用Json.reads[Type] 来简单地生成您需要的格式,而无需手动操作。

implicit val positionFormat = Json.format[Position]

【讨论】:

  • 将域模型与 json 员工耦合是您应该避免的事情之一。格式化程序主要用于 api/service/web 模块。但是,域模型本身来自业务问题,与您希望如何向客户表示它们无关。我确信没有人喜欢更改域模型以添加新的格式化程序,例如 ProtoBuf、Avro、XML ......
  • 嗨@SorooshSarabadani 您有一个简单的 Play 应用程序,适合刚入门的人。大多数人都有他们混合到所有事物中的公里数特征,这是一条可行的路,但是对于简单的场景,您为什么要过度复杂化呢?
  • 嗨 Flavian,我只是在解释为什么有经验的开发人员往往会忘记这么简单的事情 ;)
  • @SorooshSarabadani 别担心,我知道你的角度,我同意。但是上面的模式让生活稍微轻松一些,因为你不需要记住导入东西,你可以避免任何难以调试的自动魔术隐式错误。如果你不是在构建基于 protobuf 的微服务,而大多数时候你不是,那么这很简单。
  • 即使你没有构建基于 protobuf 的微服务,我相信你也不喜欢在你的域模块中依赖 play-json
【解决方案2】:

只需将你的隐式方法放在一个对象中并以这种方式导入它:

import JsonConversion._

从性能的角度来看,您不应该有任何顾虑,因为可以执行许多调用而没有副作用。

【讨论】:

  • 谢谢你 Soroosh Sarabadani,我正在考虑在将 Position 转换为 Json 的每个函数的范围内有一个实例(一个实例化类:objectif 但不是单例)?没有副作用的事实意味着可以从单例中以并发方式调用该函数?
  • 您实际上并不需要这样做,也不必担心可伸缩性。由于您的类没有状态,因此多次实例化它对您没有任何结果。引用透明性是毫无问题地以并发方式调用方法的一个很好的理由。可以执行数十亿次此类函数的并发调用,而不会产生任何类型的瓶颈或问题。
猜你喜欢
  • 2016-08-03
  • 1970-01-01
  • 1970-01-01
  • 2017-04-27
  • 2020-01-04
  • 2013-03-08
  • 1970-01-01
  • 2016-01-23
  • 2023-03-04
相关资源
最近更新 更多