Scala学习笔记 之 抽象成员

在类(class)和特质(trait)的定义中,如果某成员之给出了声明,而并没有给出定义,则这种成员成为抽象成员。抽象成员需要在其子类型中实现。具有抽象成员的类无法被实例化。

四种抽象成员

Scala中抽象成员有四种,即抽象类型(type)、抽象字段(val, var)和抽象方法( def)。

看下面的例子:

1
2
3
4
5
6
trait Abstract {
type T
def transform(x: T): T
val initial: T
var current: T
}
1
2
3
4
5
6
class Concrete extends Abstract {
type T = String
def transform(x: String) = x + x
val initial = "hi"
var current = initial
}

抽象成员的重写

如果子类中要给出父类中抽象成员的实现,是不需要写override关键字的,因为只是需要给出实现而已,并没有重写的行为。那这里所说的重写是什么意思呢?

在Scala中,如果定义一个无参数的方法,则可以省去括号。这样在调用这个方法时也就不需要加括号。在这种情况下,调用这样的方法看起来和访问某字段是一样的。而对于抽象成员,同名的抽象方法甚至可以被常量val重定义,这就是抽象成员的重写

看下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
abstract class Fruit {
val v: String // ‘v’ for value
def m: String // ‘m’ for method
}
abstract class Apple extends Fruit {
val v: String
val m: String // OK to override a ‘def’ with a ‘val’
}
abstract class BadApple extends Fruit {
def v: String // ERROR: cannot override a ‘val’ with a ‘def’
def m: String
}

可以看到,抽象的def被同名的val重写了,而反过来则是不被允许的。上例中Fruitv看作是一个常量字段,那么访问该字段就应该是简单的取值而已,而如果用def覆盖了它,那么对v的访问就变成了执行某一段程序,这于逻辑是不合的。但是相反的情况则是合乎逻辑的。