Scala Monkey Patching与Ruby相比

时间:2015-07-22 10:56:42

标签: ruby scala monkeypatching

在Scala中你可以使用implicits进行Monkey Patching但昨天我在ruby中用Fixnum看到了这个例子,这是一个愚蠢的事情,但我想在scala中实现它

class Fixnum

  def to_roman
    'I'*self #only works until 3, but only for this purpose 
  end

   def +(other)
      self - other
   end
end


puts 2.to_roman #This prints "II"
puts 1 + 1 #This prints 0

然而在scala中,我无法使用+(逆)方法

object TestImplicits extends App {

  implicit class ReverseInt(val original: Int) extends AnyVal {

    def toRoman = { "I" * original }

    def +(other:Int){
      original - other
    }
  }

  println(5.toRoman) // prints IIIII
  println( 5 + 3 )  // prints 8

}

另外,scala不像Ruby那样有全局猴子补丁吗?

2 个答案:

答案 0 :(得分:2)

Scala只会尝试为未找到的方法找到隐式转换。由于Scala找到toRoman方法,因此它不会尝试查找隐式转换,而不是Int,其中Scala 找到方法,因此将使用toRoman方法搜索从select a.cekckInTime, b.CheckOutTime from (select ROW_NUMBER() Over( ORDER BY CekckInTime ) as Id, * from attendancetable where cekckInTime is not null) a inner join (select ROW_NUMBER() Over( ORDER BY CheckOutTime ) as Id, * from attendancetable where CheckOutTime is not null) b on a.Id =b.Id 到某种类型的隐式转换。

答案 1 :(得分:1)

这很接近:

class WrappedInt(val n: Int) {
  def + (other: Int): Int = {
    n - other
  }
}
implicit def unpack(wi: WrappedInt): Int = {
  wi.n
}

// usage
val wrapped = new WrappedInt(5)
println(wrapped + 3)  // performs 5 - 3
println(wrapped * 2)  // 5 * 2 (`unpack` is called first)

但请注意,如果将WrappedInt传递给期望Int的方法,则该方法将对展开的值进行操作,因此“patch”在该方法中不会处于活动状态:

def addOne(n: Int) = {
  n + 1
}
println(addOne(new WrappedInt(5)))  // Prints 6 (no patch)

我认为最好不要允许全局修补 - 这是非常危险的,因为没有任何迹象表明,如果你正在孤立地看一个类,那么已经修补了一些东西。项目中的每个人都需要学习和记忆所有这些无形的事情。如果您正在处理多个项目,则需要记住哪个项目有哪个补丁。使用Scala时,必须显式导入第三方隐含,因此在当前文件或范围中有一些指示表明存在特殊情况。

Ruby有优化,但是don't seem very popular,可能是因为修补在文化中是如此简单和根深蒂固。