2015-07-22 4 views
1

В Scala можно сделать обезьян заплат с помощью implicits, но вчера я увидел этот пример в рубин Жека 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 

однако в Скале я не могу работать метод + (Инверсия)

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 does't имеет глобальный обезьяний заплаток, как Ruby?

ответ

2

Скала будет пытаться найти неявное преобразование для методов, которые не найдены. Поскольку Scala находит метод Int.+, он не будет пытаться искать неявное преобразование, в отличие от toRoman, где Scala не найти метод и таким образом будет искать неявное преобразование от Int к некоторому типу с toRoman метод.

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, этот метод будет работать на развернутом значении, так что «заплатка» не будет активным внутри метода:

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

Я думаю, что это лучше, чтобы не допустить глобального заплаток - это очень опасно, потому что там никаких признаков того, что-то не было исправлено, если вы смотрите на класс в изоляции. Каждому в проекте нужно будет узнать и запомнить все эти вещи, которые происходят невидимо. И если вы работаете над несколькими проектами, вам нужно будет запомнить, какой проект имеет патч. С Scala сторонние импликации должны быть явно импортированы, поэтому в текущем файле или области есть какое-то указание, что что-то особенное происходит.

Ruby имеет уточнения, но они don't seem very popular, вероятно, потому, что исправление настолько легко и укоренилось в культуре.

Смежные вопросы