抽象的语法:
(1)定义抽象类:abstract class Animal{} //通过abstract关键字标记抽象类
(2)定义抽象属性:val|var name:String //一个属性没有初始化,就是抽象属性
(3)定义抽象方法:def hello():String //只声明而没有实现的方法,就是抽象方法
抽象类举例
abstract class animal{
val name:String
val age:Int
def test(name:String):Unit
// 非抽象的属性和方法
val name1:String = "ls"
var age1:Int = 10
def test1(name:String):Unit = {
println(s"hi $name")
}
注意: 具体的类不能有抽象的属性和方法
抽象的属性和方法指没有等号,没有后面的具体内容
继承&重写
(1)如果父类为抽象类,那么子类需要将抽象的属性和方法实现,否则子类也需声明为抽象类。
(2)重写非抽象方法需要用override修饰,重写抽象方法则可以不加override。
// 抽象的类需要有子类继承并重写才能使用
// scala当中属性也能够进行重写 -> 因为属性具有方法的特性
class lion extends animal{
override val name: String = "lion"
override var age: Int = 6
override def test(name: String): Unit = {
println(s"$name")
// 可以重写不可变的属性
override val name1: String = "lisi"
// 可以重写方法
override def test1(name: String): Unit = {println("hi")}
// 可变的属性不能够重写 -> 因为可变的属性能够直接在子类中修改
age1 = 20
}
}
(3)子类中调用父类的方法使用super关键字
(4)子类对抽象属性进行实现,父类抽象属性可以用var修饰;
子类对非抽象属性重写,父类非抽象属性只支持val类型,而不支持var。
因为var修饰的为可变变量,子类继承之后可以直接使用,不用重写。
(5)多态
// 多态
// 父类的引用指向子类的实例
// 自动类型推断无法使用多态
// 多态无法使用到子类独有的方法,只能使用父类中已经存在的方法
val lion: animal= new lion
println(lion.name)
println(lion.age)
println(lion.test("ls2"))
Scala中属性和方法都是动态绑定,而Java中只有方法为动态绑定。
java会调用子类重写的方法,父类的属性
scala中的多态比较特殊,属性和方法都会使用子类的
(6)匿名子类
// 使用匿名子类完成抽象类的使用
// 直接创建抽象类的对象 会自动生产匿名子类来实现
// 匿名子类默认一定使用多态 所以匿名子类中写的自定义方法外部都无法调用
val animal01: animal = new animal {
override val name: String = "tiger"
override val age: Int = 5
override def test(food: String): Unit = {
println("awu")
eat(food)
}
// 自定义的方法在匿名子类中 只能在类内部使用
def eat(n:String): Unit = {println("吃"+ n)}
}
println(animal01.name)
println(animal01.age)
animal01.test("meat")