7.2 选择性混入

在上面的例子里,Friend trait混入到了Dog类里。这样就可以将Dog任意实例当作Friend;也就是说,所有的Dog都是Friend

此外,还可以在实例一级对trait进行选择性混入,这样的话,就可以把特定的类的实例当做trait。我们看个例子:

TraitsAndTypeConversions/Cat.scala

  1. class Cat(val name: String) extends Animal

Cat并没有混入Friend trait,所以,不能把Cat的实例当作Friend。下面会看到,尝试这么做就会导致编译错误:

TraitsAndTypeConversions/UseCat.scala

  1. def useFriend(friend: Friend) = friend listen
  2. val alf = new Cat("Alf")
  3. val friend : Friend = alf // ERROR
  4. useFriend(alf) // ERROR

错误如下:

  1. (fragment of UseCat.scala):4: error: type mismatch;
  2. found : Cat
  3. required: Friend
  4. val friend : Friend = alf // ERROR
  5. ^
  6. (fragment of UseCat.scala):6: error: type mismatch;
  7. found : Cat
  8. required: Friend
  9. useFriend(alf) // ERROR
  10. ^
  11. two errors found
  12. !!!
  13. discarding <script preamble>
  14. !!!
  15. discarding <script preamble>

然而,Scala确实可以为爱猫人提供帮助,需要的话,我们可以专门把特殊的宠物当作Friend。创建实例时,只要简单的用with关键字标记一下即可:

TraitsAndTypeConversions/TreatCatAsFriend.scala

  1. def useFriend(friend: Friend) = friend listen
  2. val snowy = new Cat("Snowy") with riend
  3. val friend : Friend = snowy
  4. friend.listen
  5. useFriend(snowy)

输出如下:

  1. Your friend Snowy is listening
  2. Your friend Snowy is listening

Scala给予了我们极大的灵活性:把类的所有实例当作trait,或是只选择需要的实例当作trait。如果想把trait用于事先存在的类上,后者就显得有用了。