【问题标题】:scala: class can't access companion object members externallyscala:类无法从外部访问伴随对象成员
【发布时间】:2018-01-17 09:18:27
【问题描述】:

如下我定义了一个 MapModel 类和它的伴生对象。

class MapModel(val map: Map[String, Double])

object MapModel {
  implicit def MapToMapModel(map: Map[String, Double]) = new MapModel(map)

  def apply(map: Map[String, Double]) = new MapModel(map)

  /**
    * weighted sum
    *
    * @param other
    * @param weight
    * @return
    */
  def +*(other: MapModel, weight: Double): MapModel = {
    ???
  }
  def test(): Unit ={

  }
}

我想创建一个 MapModel 实例并调用 +* 方法。但是无法找到伴随对象中的所有方法。 例如,我有一个jm 实例,它是一个Map[String,Double]

MapModel(jm).test()

产生错误,说

值测试不是 MapModel 的成员

【问题讨论】:

  • 应直接访问伴随对象的成员,如MapModel.test()
  • 那么伴生对象不是类的实例吗?
  • 伴生对象是类的单例实例。 MapModel(jm) 调用伴生对象的apply() 方法,在这种情况下,它是一个返回MapModel 实例的工厂方法。由于test()是对象上的方法,而不是类,所以不能在工厂方法的返回值上调用它。

标签: scala


【解决方案1】:

在类/特征的伴生对象上定义的方法在该类型的任何实例上都不可见,而只能通过显式调用伴生对象本身的方法来实现。

您似乎正在寻找语法之类的扩展方法。您可以通过implicit class

implicit class MapModelOps(val mapModel: MapModel) extends AnyVal {
  def +*(other: MapModel, weight: Double): MapModel = {
    ???
  }
}

现在可以了:

def main(args: Array[String]): Unit = {
  val map = MapModel(Map("s" -> 1.0))
  val res = map +* (MapModel(Map("v" -> 2.0)), 3.0)
}

或者,如果您可以访问底层类,则可以将方法放入其中。

【讨论】:

  • Yuval,如果 Tyler 控制了伴生对象,这意味着他也控制了主类。在这种情况下,为什么 +* 应该作为扩​​展方法实现,而不是像 Nicolas 那样作为 MapModel 本身内部的方法实现?
  • @SergGr 这就是为什么我在底部评论说这取决于他。这是 IMO 风格的问题,取决于你想怎么做,两种方式都行。
【解决方案2】:

对象MapModel 没有MapModel 类型(令人困惑的是,它有MapModel.type 类型)。

如果你想给MapModel添加方法,你需要把它们添加到类中。例如,您的 +* 方法在伴随对象中几乎没有意义:

class MapModel(val map: Map[String, Double]) {
  def +*(other: MapModel, weight: Double): MapModel = new MapModel(map ++ other)
}

【讨论】:

    【解决方案3】:

    有时,使用类实例授予对所有伴随对象成员的访问权限可能很有用。可以使用以下隐式转换来实现:

    implicit def mapModelAcessCompanion(m: MapModel): MapModel.type = MapModel
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-06
      • 1970-01-01
      • 2013-06-05
      相关资源
      最近更新 更多