抽象
scala的抽象关键字和java一样,都是abstract
,而且抽象类都不能被实例化的。
除了类可以定义为抽象的,类的属性和方法,也可以是抽象的。
从下面的例子中,可以看到其实和java的抽象类定义没有什么区别
abstract class ScalaAbstract {
// 抽象属性,可以没有初始值,甚至不用_
var str1: String
var str2: String = "str2"
val str3: String
val str4: String = "str4"
/**
* 抽象方法
*/
def printInfo1: Unit
def printInfo2: Unit = {
println(s"${str1},${str2},${str3},${str4}")
}
}
继承
和java一样,继承也是用extends
关键字,概念也是同java的,包括先调用父类的构造器等。区别如下:
- 如果覆盖父类的非抽象方法,非抽象变量,在scala中要写override,在java中只是警告。
- 抽象方法,var定义的抽象变量,可以不写override,也可以写。
- val定义的抽象变量,要写override。
class ScalaChild extends ScalaAbstract {
/**
* 可以不写override
*/
var str1: String = "str1"
/**
* 直接修改
*/
str2 = "str2"
/**
* 必须写override
*/
override val str3: String = "str3"
/**
* 必须写override
*/
override val str4: String = "str4"
/**
* 抽象方法,可以不写override
*/
def printInfo1: Unit = {
println(s"${str1},${str2},${str3},${str4}")
}
/**
* 必须写override
*/
override def printInfo2: Unit = {
println(s"ScalaChild:${str1},${str2},${str3},${str4}")
}
}
object ScalaChild {
def main(args: Array[String]): Unit = {
val child = new ScalaChild()
child.printInfo1
child.printInfo2
}
}
多态
我们先看看比较熟悉的java。
定义了一个抽象类JavaAnimal,包含一个变量name和方法eat。JavaCat和JavaDog是JavaAnimal的实现类。在main方法中通过eat方法打印。
public abstract class JavaAnimal {
public String name = "无";
abstract void eat();
}
public class JavaCat extends JavaAnimal {
String name = "小猫";
void eat() {
System.out.println("吃鱼");
}
}
public class JavaDog extends JavaAnimal {
String name = "小狗";
void eat() {
System.out.println("吃骨头");
}
}
public class JavaAnimalMain {
public static void eat(JavaAnimal animal) {
System.out.println(animal.name);
animal.eat();
}
public static void main(String[] args) {
eat(new JavaCat());
eat(new JavaDog());
}
}
打印结果为:
无
吃鱼
无
吃骨头
可以看到name为父类的值,但是方法却是调用子类的方法。
在scala中,实现类似的功能:
abstract class ScalaAnimal {
var name: String = "无"
def eat(): Unit
}
object ScalaAnimal {
def eat(animal: ScalaAnimal): Unit = {
println("******")
println(animal.name)
animal.eat()
}
def main(args: Array[String]): Unit = {
eat(new ScalaCat)
eat(new ScalaDog)
}
}
class ScalaCat extends ScalaAnimal {
name = "小猫"
override def eat(): Unit = {
println("吃鱼")
}
}
class ScalaDog extends ScalaAnimal {
name = "小狗"
override def eat(): Unit = {
println("吃骨头")
}
}
打印结果:
******
小猫
吃鱼
******
小狗
吃骨头
name打印的是子类的name。
所以java中属性是静态绑定,方法是动态绑定。而scala中,属性和方法都是动态绑定。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。