从多个隐式对象自动导入

时间:2016-04-17 08:42:01

标签: scala typeclass

我刚刚找到了Scala的类型类概念,并且非常喜欢它。问题我发现我发现的所有例子都把类型(对象)放在一个对象下(比如这里:http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html

也许这是错的,但我是每个班级有一个文件的朋友。所以我喜欢做的是将类型类放入几个文件中,这意味着每个实现都需要放入一个单独的对象中。这现在导致了问题"我需要手动导入每个实现。为了更好地澄清一个小例子:

package sth

import sth.like.Like
import sth.like.StringLike._
import sth.like.IntLike._

object Application extends App {
    def t[T](arg: T)(implicit l: Like[T]) = {
        l.print(arg)
    }

    t(1)
    t("Blub")
}

-

package sth.like

trait Like[T] {
    def print(arg: T)
}

-

package sth.like

object IntLike {
    implicit object LikeIntLike extends Like[Int] {
        def print(arg: Int): Unit = println(s"INT $arg")
    }
}

-

package sth.like

object StringLike {
    implicit object LikeStringLike extends Like[String] {
        override def print(arg: String): Unit = println(s"STRING: $arg")
    }
}

到目前为止这是有效的。我知道,Application中的通配符导入不是必需的,但这不是重点。如您所见,我需要在Application中导入StringLike和IntLike,否则它们不适用于Application对象。

那么可以通用的方式做到这一点,还是以这种方式做到这一点是完全不好的做法?

2 个答案:

答案 0 :(得分:4)

你可以把你的暗示放在特征中,而不是对象

trait IntLike {
  implicit object LikeIntLike extends Like[Int] {
    def print(arg: Int): Unit = println(s"INT $arg")
  }
}

然后让对象具有相同的名称,扩展这个特性,这将为您提供前面的内容,您可以单独导入每个内容。

object IntLike extends IntLike

您可以对类型类的所有其他实例执行相同的操作:

trait StringLike {
  implicit object LikeStringLike extends Like[String] {
    override def print(arg: String): Unit = println(s"STRING: $arg")
  }
}

object StringLike extends StringLike

在另一个文件中,您可以将所有特征组合在一起:

object Implicits extends StringLike with IntLike

并仅导入Implicits对象,如果您想要所有隐含的范围。

package sth

import sth.like.Like
import sth.like.Implicits._

object Application extends App {
  def t[T](arg: T)(implicit l: Like[T]) = {
    l.print(arg)
  }

  t(1)
  t("Blub")
}

您可以选择混合您需要的特征

object Application extends App with StringLike with IntLike { ... }

甚至

trait Implicits extends StringLike with IntLike
object Implicits extends Implicits

object Application extends App with Implicits { ... }

答案 1 :(得分:0)

非常感谢你的回答。但我还需要手动将新类型类添加到Implicits,不是吗?

出于简单原因,我不能使用then包对象:

http://naildrivin5.com/scalatour/wiki_pages/PackageObjects/

我的意思是这一部分:

package opower {
   package object controller {
       type Secured = org.springframework.security.access.annotation.Secured
       type Controller = org.springframework.stereotype.Controller
       ...
   }
}

由于似乎没有动态方法,我可以将所有类型类放入控制器对象中,然后可以导入。

或者我是否会错过理解包对象?