1. 

There’s a fundamental difference between your own code and libraries of

other people: you can change or extend your own code as you wish, but if

you want to use someone else’s libraries, you usually have to take them as

they are.

你可以改变或扩展自己的代码,但是对别人的代码只能原样接受

2.

A number of constructs have sprung up in programming languages to

alleviate this problem. Ruby has modules, and Smalltalk lets packages add

to each other’s classes. These are very powerful, but also dangerous, in that

you modify the behavior of a class for an entire application, some parts of

which you might not know

编程语言发展出很多方法解决这个问题。Ruby有module, Smalltalk。。。,这些方法很强大,也很危险。你改变了一个类的行为,这对整个应用程序都会产生影响。有些影响是无法预知的。

3.

 C# 3.0 has static extension methods, which are

more local, but also more restrictive in that you can only add methods, not

fields, to a class, and you can’t make a class implement new interfaces

C#3.0允许你给类添加新的方法,但不能添加field,也不能使类实现新的接口

4.Scala’s answer is implicit conversions and parameters

Scala的答案是隐式转化和隐式参数


5. 隐式转化的典型应用

Before delving into the details of implicit conversions, take a look at a typical

example of their use. Implicit conversions are often helpful for working with

two bodies of software that were developed without each other in mind. Each

library has its own way to encode a concept that is essentially the same thing.

Implicit conversions help by reducing the number of explicit conversions that

are needed from one type to another.

每个package都有自己的方法表示某个概念。不同包用不同方法表示的概念本质上可能是相同的。这这时可以用隐式转化


6. 示例1

Java Swing包的ActionListener是只有一个方法的接口。Java就是用这种方式实现了类似函数的功能。

  val button = new JButton
  button.addActionListener(
    new ActionListener {
      def actionPerformed(event: ActionEvent) {
        println("pressed!")
      }
    })

Scala中可以直接传递一个函数给addActionListener方法

  button.addActionListener( // Type mismatch!
    (_: ActionEvent) => println("pressed!"))

但是直接这样写会出现类型不匹配,我们还需定义一个转化方法,让编译器自动做转化

implicit def function2ActionListener(f: ActionEvent => Unit) =
new ActionListener {
def actionPerformed(event: ActionEvent) = f(event)
}

编译器的转化过程

The way this code works is that the compiler first tries to compile it as is, but

it sees a type error. Before giving up, it looks for an implicit conversion that

can repair the problem. In this case, it finds function2ActionListener. It

tries that conversion method, sees that it works, and moves on. The compiler

works hard here so that the developer can ignore one more fiddly detail.

Action listener? Action event function? Either one will work—use the one

that’s more convenient.


7. 隐式转化的规则

Implicit definitions are those that the compiler is allowed to insert into a

program in order to fix any of its type errors. For example, if x + y does

not type check, then the compiler might change it to convert(x) + y, where

convert is some available implicit conversion. If convert changes x into

something that has a + method, then this change might fix a program so that it

type checks and runs correctly.

如果x没有 + 这个方法,就试图转换x的类型。 为什么转化x而不转化y呢? 因为 + 是左结合的运算符

还有个典型的隐式转化是stream的 #:: 方法。


Marking Rule: Only definitions marked implicit are available

只有标记为 implicit的方法才可以用来做隐式转化


Scope Rule: An inserted implicit conversion must be in scope as a single

identifier, or be associated with the source or target type of the conversion

1.作用域内的单标识符函数才可以。abc.def这样的函数是不可以的,因为它不是单标识符。

2.查找与source type关联的companion object中是否定义了隐式转化函数。例如

object Steam {
  /** A wrapper method that adds `#::` for cons and `#::: for concat as operations
   *  to streams.
   */
  implicit def consWrapper[A](stream: => Stream[A]): ConsWrapper[A] =
    new ConsWrapper[A](stream)
}


Naming an implicit conversion. Implicit conversions can have arbitrary

names.  名字任意取, 无所谓