Scala委托导入隐式转换

时间:2012-10-15 18:14:05

标签: scala object import delegates implicit-conversion

在Scala中,如何将隐式转换的导入委托给我的作用域,这样我就不必拥有一个大的“环境”类,它提供了库函数/值(对于我正在创建的DSL)以及隐式转换?

简而言之,我可以从对象移动隐式转换,并在写入时仍然导入它:

导入MyDslEnvironment ._

这样做的目的是使我的框架的导入和使用变得简单和轻量级,因为只有一个import语句为用户提供了我的DSL /框架所需的功能。

PS:在任何人为我开火之前 - 是的,我知道可能来自隐含转换的陷阱和肮脏。

2 个答案:

答案 0 :(得分:3)

这可以通过使用特征来实现。只需根据需要定义隐式转换(实现模块化),并在单个对象(MyDslEnvironment)中混合特征。例如:

case class Foo( value: Int )
case class Bar( value: String )
object Baz {
  def test( foo: Foo, bar: Bar ) { println( foo + "," + bar ) }
}

trait ImplicitEnv1 {
  implicit def toFoo( value: Int ) = Foo( value )
}

trait ImplicitEnv2 {
  implicit def toBar( value: String ) = Bar( value )
}

object MyDslEnvironment extends ImplicitEnv1 with ImplicitEnv2

然后你可以这样做:

scala> import MyDslEnvironment._
import MyDslEnvironment._
scala> Baz.test( 123, "hello" )
Foo(123),Bar(hello)

您实际上可以将所有代码(FooBarBaz放在上面的示例中)放在特征中,而不仅仅是隐式转换(这可能需要使用自我 - 类型注释)。在这一点上,你将基本上实现(in)着名蛋糕模式的变体之一。 见http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di/

答案 1 :(得分:3)

我的倾向是将隐含物放在包装物中。

假设您的工作将在com.acme.mydsl包中定义。您的源文件排列在目录层次结构com>中。 acme>看MyDSL。在目录mydsl中,定义一个如下对象:

package com.acme; //we are in the mydsl dir, but note no mydsl in
                  //in the package declaration

package object mydsl {

   implicit def idioticallyStringsAre5( s : String ) : Int = 5

   //define other utilities that should be available within
   //the package or importable

}

现在,你可以这样做:

scala> import com.acme.mydsl._
import com.acme.mydsl._

scala> def sum( a : Int, b : Int ) = a + b
sum: (a: Int, b: Int)Int

scala> sum("hello", "there")
res0: Int = 10

通过导入导入com.acme.mydsl._,您获得了所有包级别的函数定义,包括隐式转换。

我真的很喜欢包对象。在Java中,为了实用函数,必须使类充满静态成员。包对象充当这些实用程序的非常优雅的名称空间,包括隐式转换。