类的继承
继承是一种描述类与类之间的关系,反映的是“is a”这种关系。子类通过关键字extends继承了父类的字段和方法,同时可以自定义相应的字段和方法。
需要注意的是,如果父类中的成员,包括父类被final关键字修饰了,则无法被继承和覆盖。同样的,如果父类成员被private关键字修饰之后,子类也无法继承或是覆盖。
当有继承体系的时候,在用子类构造器创建对象的时候,先调用父类的构造器。
子类调用父类成员,如果子类没有重名的,直接成员名,如果有重名的,需要使用super来调用。也就是说,在父类中定义方法,通过“super.方法名”调用即可。
Scala中是无法直接调用父类构造器,是间接调用父类构造器,只能是主构造器调用父类的构造器,辅助构造器是不能直接调用父类的构造器。
// 基类
class Vehicle(speed: Int) {
def race() = println("赛车")
}
// 派生类:只有主构造函数可以将参数传递给基构造函数
class RacingCar(speed: Int, color: String) extends Vehicle(speed) {
override def race() = println("Racing Car")
def info = println(s"速度:$speed, 颜色:$color")
}
// 另一个子类
class Bike(speed:Int, model:String) extends Vehicle(speed) {
override def race() = println("Racing Bike")
def detail = println(s"速度:$speed, 品牌:$model")
}
object Demo3 {
def main(args: Array[String]) {
// 对象
val vehicle1 = new RacingCar(200,"red")
vehicle1.race
vehicle1.info
println("-----------------------")
val vehicle2 = new Bike(100,"绿佳")
vehicle2.race
vehicle2.detail
println("-----------------------")
// 多态
var veh: Vehicle = new RacingCar(250,"blue")
println(veh.kph)
veh.race
veh = new Bike(150,"爱玛")
println(veh.kph)
veh.race
}
}
在处理类和对象层次结构时,通常会有一个封装公共行为的基类。例如,让我们创建一个抽象类名Donut,它为printName定义了一个方法签名。
abstract class Donut(name: String) {
def printName: Unit
}
任何扩展abstract类Donut的类都必须提供printName方法的实现。
要创建抽象Donut类的子类,必须使用extends关键字、传递name构造函数参数并为printName方法提供实现。如下面的示例所示,类VanillaDonut扩展了抽象类Donut,并提供了printName方法的实现。
// 伴生类
class VanillaDonut(name: String) extends Donut(name) {
override def printName: Unit = println(name)
}
// 伴生对象
object VanillaDonut {
def apply(name: String): Donut = {
new VanillaDonut(name)
}
}
定义另一个子类GlazedDonut,从抽象类Donut继承。
class GlazedDonut(name: String) extends Donut(name) {
override def printName: Unit = println(name)
}
object GlazedDonut {
def apply(name: String): Donut = {
new GlazedDonut(name)
}
}
让我们创建两个Donut对象,一个使用VanillaDonut类,另一个使用GlazedDonut类。请注意,我们将vanillaDonut和glazedDonut的类型指定为基本类型Donut。
object InheritanceDemo {
def main(args: Array[String]): Unit = {
val vanillaDonut: Donut = VanillaDonut("Vanilla Donut")
vanillaDonut.printName
val glazedDonut: Donut = GlazedDonut("Glazed Donut")
glazedDonut.printName
}
}
case类继承
创建抽象Donut类的子类,必须使用extends关键字、传递name构造函数参数并为printName方法提供实现。
如下面的示例所示,case类VanillaDonut2扩展了抽象类Donut,并提供了printName方法的实现。
case class VanillaDonut2(name: String) extends Donut(name) {
override def printName: Unit = println(name)
}
与之前的类继承不同,我们不需要为VanillaDonut2 case类创建一个伴生对象,因为case类将自动提供一个伴生对象。 创建另一个case类GlazedDonut2,它扩展了抽象Donut类。
case class GlazedDonut2(name: String) extends Donut(name) {
override def printName: Unit = println(name)
}
同样,我们不需要为VanillaDonut2 case类创建一个伴生对象,因为case类将自动提供一个伴生对象。
让我们创建两个Donut对象,一个使用VanillaDonut2类,另一个使用GlazedDonut2类。请注意,我们将vanillaDonut2和glazedDonut2的类型指定为基本类型Donut。
object InheritanceDemo {
def main(args: Array[String]): Unit = {
val vanillaDonut2: Donut = VanillaDonut2("Vanilla Donut")
vanillaDonut2.printName
val glazedDonut2: Donut = GlazedDonut2("Glazed Donut")
glazedDonut2.printName
}
}
多态
在Scala继承中,Scala向父类的构造器传递参数。
Java中多态,父类引用指向子类对象,例如:
Fu zi = new zi();
Scala中多态的体现:
val zi:Fu = new zi()
多态类型,编译时看=的左边,运行要看=的右侧。
class Worker(name:String, age:Int) {
var language:String = _
def show(): Unit = {
println(s"name is $name,, and age is $age")
}
}
class Coder(name:String, age:Int, language:String) extends Worker(name, age) {
def this() {
this("程序员", 18, "Java")
}
override def show(): Unit = {
println(s"name is $name, and age is $age, language is $language")
}
}
val coder:Worker = new Coder("xpleaf", 23, "scala")
coder.show()
1 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
2 本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
3 本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。
暂无评论内容