我一直在学习Scala用于网络开发很长一段时间,我偶然发现缺少接口。来自PHP,我使用了很多方法级别的多态性和IoC这样的接口:
interface iAnimal
{
function makeVoice();
}
class Cat implements iAnimal
{
function makeVoice()
{
return "Meow";
}
}
class Dog implements iAnimal
{
function makeVoice()
{
return "Woof!";
}
}
class Box
{
private $_animal;
function __construct(iAnimal $animal)
{
$this->_animal = $animal;
}
function makeSound()
{
echo $this->_animal->makeVoice();
}
}
等等,这是一种简单的方法,可以确保我传递给Box
对象的任何内容都有makeVoice
方法,我在其他地方调用它。现在,我很好奇的是,我如何使用Scala实现类似的功能。我试着寻找这个,但信息非常稀少。我找到的唯一答案是使用特征,但据我所知,它们用于具体实现,而不是声明。
提前致谢。
答案 0 :(得分:5)
根据其他答案,解决方案是使用特征:
trait Animal {
def makeVoice(): Unit //no definition, this is abstract!
}
class Cat extends Animal{
def makeVoice(): Unit = "Meow"
}
class Dog extends Animal{
def makeVoice(): Unit = "Woof"
}
class Box(animal:Animal) {
def makeSound() = animal.makeVoice()
}
Scala中的trait
将直接编译为Java中的interface
。如果它包含任何具体成员,那么这些将直接复制到任何继承该特征的类中。您可以愉快地使用Scala特性作为Java的接口,但是您没有为您混合使用具体功能。
然而......这只是图片的一部分。到目前为止我们实现的是子类型多态,Scala也允许ad-hoc多态(a.k.a类型类):
// Note: no common supertype needed here
class Cat { ... }
class Dog { ... }
sealed trait MakesVoice[T] {
def makeVoice(): Unit
}
object MakesVoice {
implicit object CatMakesVoice extends MakesVoice[Cat] {
def makeVoice(): Unit = "Meow"
}
implicit object DogMakesVoice extends MakesVoice[Dog] {
def makeVoice(): Unit = "Woof"
}
//helper method, not required, but nice to have
def makesVoice[T](implicit mv: MakesVoice[T]) = mv
}
import MakesVoice._
//context-bound version
class Box[T : MakesVoice] {
//using a helper:
def makeSound() = makesVoice[T].makeVoice()
//direct:
def makeSound() = implicitly(MakesVoice[T]).makeVoice()
}
//using an implicit param
class Box[T](implicit mv : MakesVoice[T]) {
def makeSound() = mv.makeVoice()
}
这里重要的是MakesVoice
类型类可以与任何类型相关联,无论它属于哪个层次结构。您甚至可以使用从第三方库导入的基元或类型的类型类,这些基类或类型无法使用新接口进行改造。
当然,你也有参数多态性,你可能更熟悉“泛型”:)
答案 1 :(得分:1)
Traits用于声明和具体实现。这是您的示例的直接翻译
trait Animal {
def makeVoice()
}
class Cat extends Animal{
override def makeVoice(): Unit = "Meow"
}
class Dog extends Animal{
override def makeVoice(): Unit = "Woof"
}
class Box(animal:Animal) {
def makeSound()={
animal.makeVoice()
}
}
此外,您可以直接在特征中定义具体实现,这对不同类层次结构的成员共享的行为很有用:
trait Fish{
def swim()="Swim"
}
class Truit extends Fish
trait Bird{
def fly() = "Fly"
}
class Eagle extends Bird
class Duck extends ???{
def swim=???
def fly=???
}
鸭子都会游弋苍蝇,你可以这样定义:
trait Swimmer{
def swim
}
trait Fish extends Swimmer{
def swim()="Swim"
}
class Truit extends Fish
trait Bird{
def fly()="Fly"
}
class Eagle extends Bird
class Duck extends Bird with Swimmer