对于Mixin(混入)、Trait这两个面向对象特性,总是让人觉得说不清道不明的感觉,其实众多设计语言里,这里面的一些概念也是相互参杂的,并不是又那么一个严格的定义或界限说哪种一定是Mixin,或者哪种一定是Trait。这两种语言设施的提出,它的本质实际上都是解决代码复用的问题。下面我们局一些例子来说明。介于本人的认识有限,在此也只是说说自己的看法。
多继承 VS 单继承
引用The developers of the Java language were well-versed in C++ and other languages that include multiple inheritance, whereby
classes
can inherit from an arbitrary number of parents. One of the problems with multiple inheritance is that it's impossible to determine which parent inherited
functionality is derived from. This problem is called the diamond problem (see Resources). The diamond problem and other complexities that are inherent in multiple inheritance inspired the Java language designers to opt for single inheritance plus interfaces.
Interfaces define semantics but not behavior. They work well for defining method signatures and data abstractions, and all of the Java.next languages support Java interfaces with no essential changes. However, some cross-cutting concerns don't fit into a single-inheritance-plus-interfaces model.
在Java 中,一个类可以实现任意数量的
接口。这个模型在声明一个类实现多个抽象的时候非常有用。不幸的是,它也有一个主要缺点。对于许多接口,大多数功能都可以用对于所有使用这个接口的类都有效的“样板”代码来实现。Java 没有提供一个内置机制来定义和使用这些可重用代码。相反的,Java
程序员必须使用一个特别的转换来重用一个已知接口的实现。在最坏的情况下,程序员必须复制粘贴同样的代码到不同的类中去。
Mixin VS Trait
事实上我觉得这两个的涵义根据语言不同,而解释不同。但是它们的目的都是作为单继承不足的一种补充,或者是变相地实现多继承。实际上Java的接口也是变相的实现多继承,但是java的接口只是定义signature,没有实现体。在某种意义上Mixin和Trait这两者有点类似于抽象类,或者是有部分或全部实现体的Interface,但是在具体语言中,有表现出不一样的用法。事实上,笔者认为没有特别固定的或者是严格的区别。Mixin和Trait这两者都不能生成实例,否则就跟class没什么区别了。下面分别这两者的例子:
Scala trait
class Person ; //实验用的空类
trait TTeacher extends Person {
def teach //虚方法,没有实现
}
trait TPianoPlayer extends Person {
def playPiano = {println("I’m playing piano. ")} //实方法,已实现
}
class PianoplayingTeacher extends Person with TTeacher with TPianoPlayer {
def teach = {println("I’m teaching students. ")} //定义虚方法的实现
}
PHP traits
// the template
trait TSingleton {
private static $_instance = null;
public static function getInstance() {
if (null === self::$_instance)
{
self::$_instance = new self();
}
return self::$_instance;
}
}
class FrontController {
use TSingleton;
}
// can also be used in already extended classes
class WebSite extends SomeClass {
use TSingleton;
}
Ruby mixin
module Foo
def bar
puts "foo";
end
end
然后我们把这个模块混入到对象中去:
class Demo
include Foo
end
如上
编码后,模块中的实例方法就会被混入到对象中:
d=Demo.new
d.bar