编写了一些scala工具后,我正试图掌握安排代码的最佳方法 - 特别是暗示。我有2个目标:
为了避免重复隐含,我提出了这种结构(类似于scalaz的排列方式):
case class StringW(s : String) {
def contrived = s + "?"
}
trait StringWImplicits {
implicit def To(s : String) = StringW(s)
implicit def From(sw : StringW) = sw.s
}
object StringW extends StringWImplicits
// Elsewhere on Monkey Island
object World extends StringWImplicits with ListWImplicits with MoreImplicits
这让我只是
import StringW._ // Selective import
或(在大多数情况下)
import World._. // Import everything
其他人如何做到这一点?
答案 0 :(得分:4)
如果您不知道他们来自哪里,我认为implicit
次转化很危险。在我的情况下,我将implicit
放在Conversions
课程中,import
尽可能接近使用
def someMethod(d: Date) ; Unit {
import mydate.Conversions._
val tz = TimeZone.getDefault
val timeOfDay = d.getTimeOfDay(tz) //implicit used here
...
}
我不确定我是否喜欢“继承”来自各种trait
的隐含,因为它被认为是糟糕的Java实践来实现interface
所以你可以直接使用它的常量(首选静态导入)。
答案 1 :(得分:1)
我通常在一个对象中进行了implicit
次转换,这清楚地表明它的导入内容是implicit
转换。
例如,如果我有一个类com.foo.bar.FilthyRichString
,则隐式转换将进入com.foo.bar.implicit.FilthyRichStringImplicit
。我知道这些名称有点长,但这就是为什么我们有IDE(并且Scala IDE支持越来越好)。我这样做的方式是,我认为所有隐式转换都可以在10 second code review中清晰地查看。我可以查看以下代码:
// other imports
import com.foo.bar.FilthyRichString
import com.foo.bar.util.Logger
import com.foo.bar.util.FileIO
import com.foo.bar.implicits.FilthyRichStringImplicit._
import com.foo.bar.implicits.MyListImplicit._
// other implicits
并快速查看此源文件中处于活动状态的所有隐式转换。如果您使用导入按包分组的约定,并且在不同包之间使用新行,它们也会聚集在一起。
沿着相同的参数,我不喜欢包含所有隐式转换的catch-all对象。在一个大项目中,你真的会在所有源文件中使用所有隐式转换吗?我认为这样做意味着代码的不同部分之间的紧密耦合。
此外,一个包罗万象的对象不是很好的文档。在显式写入文件中使用的所有隐式转换的情况下,可以只查看import语句并立即跳转到隐式类的文档。对于catch-all对象,人们必须查看该对象(在大项目中可能很大),然后搜索它们之后的隐式转换。
我同意oxbow_lakes在trait
中隐含转换是不好的,因为它继承了它的诱惑,正如他所说的那样,这是不好的做法。沿着这些方向,我会使对象保持隐式转换final
只是为了完全避免诱惑。如果隐式转换只是在代码中谨慎使用,那么他将导入它们尽可能接近使用的想法也非常好。
-- Flaviu Cipcigan