我在object
中定义了隐式转化。让我们调用对象Implicits
,其中有一个隐式转换。
package com.gmail.naetmul.stackoverflow.app
object Implicits {
implicit def int_to_intEx(x: Int): IntEx = IntEx(x)
}
此对象位于某个包中。我想在包com.gmail.naetmul.stackoverflow.app
及其所有子包(如com.gmail.naetmul.stackoverflow.app.something.anything.everything
)中的每个代码中使用此隐式转换。
所以我创建了com.gmail.naetmul.stackoverflow.app
的包对象。
package com.gmail.naetmul.stackoverflow
package object app {
import com.gmail.naetmul.stackoverflow.app.Implicits._
}
但它不能在确切的包对象之外工作。
所以我将对象Implicits
更改为trait
并让包对象扩展它。
package com.gmail.naetmul.stackoverflow.app
trait Implicits {
implicit def int_to_intEx(x: Int): IntEx = IntEx(x)
}
package com.gmail.naetmul.stackoverflow
import com.gmail.naetmul.stackoverflow.app.Implicits
package object app extends Implicits {
// some code
}
隐式转换在包com.gmail.naetmul.stackoverflow.app
中有效。但是,它在子包中起作用或不起作用。
例如)
档案A.scala
package com.gmail.naetmul.stackoverflow.app.database
class A {
// Here, the implicit conversion did NOT work.
}
档案B.scala
package com.gmail.naetmul.stackoverflow.app
package database
class B {
// Here, the implicit conversion DID work.
}
所以问题是:
在这种情况下,我应该使用trait
而不是object
(使用包对象,但在外部定义)?
是否有另一种方法可以在子包中使用隐式转换?
我的意思是,只导入一次,并在任何地方使用它们。在B.scala
中工作的方式似乎很好,但Eclipse的默认包语句类似于A.scala
,因此我必须手动更改它们。
答案 0 :(得分:3)
问题1,将超类中的含义隐藏为“LowPriorityImplicits”会很有用,但这似乎不是这里的用例。
问题2,嵌套包是将implicits纳入范围的常用方法。 “packagings”中的规范9.2使用了一个神奇的短语,“在他们的简单名称下可见。”
但是有一些利用隐式范围的策略。
我从你的部分示例中猜测,你想用odd
之类的方法来增强Int。对于此用例,提供缺少的成员,您必须提供转换。
但API设计还有其他选择。例如:
鉴于API:
package goofy
object API {
def api(i: IntEx) = i.odd
}
以及子包中API的客户端:
package goofy.foo.bar.baz
import org.junit.Test
class UseIntExTest {
import goofy.API._
@Test def usage(): Unit = {
assert(api(3))
}
}
您已导入API并获得“免费”的隐式范围。
转换是在配套对象中:
package goofy
class IntEx(val i: Int) {
def even = i % 2 == 0
def odd = !even
}
object IntEx {
implicit private[goofy] def `enhanced IntEx`(i: Int): IntEx = new IntEx(i)
}
这是有效的,因为IntEx
是预期的类型。您也可以以相同的方式利用类型参数。
为完整起见,要显示转换仅限于子包:
package roofy
import org.junit.Test
class BadUsageTest {
import goofy.API._
@Test def usage(): Unit = {
//assert(api(3)) // DNC
}
}