在面向对象编程(OOP)的世界里,继承、多态和构造器是构建灵活代码的三大支柱。Scala 作为一门融合了函数式与面向对象思想的语言,对这些特性的实现既保留了 OOP 的核心逻辑,又加入了简洁的语法设计。
一、继承:从 “不劳而获” 到 “自定义改造”
1.1 基础继承:子类复用父类方法
package level02
import java.io.FileWriter
object class07 {
/*
* 继承
* extends
* 好处:不劳而获
* 问题:
* 如果父类觉得子类的方法并不是自己要的,如何定义自己的方法呢?
* 1.override 重写
* 2.super 在子类内部,通过super来访问子类
*/
// 父类:Animal(独立定义,不包含子类)
class Animal {
def run():Unit = {
}
def eating(): Unit = {
println("Animal eating")
}
}
// 子类:Dog(独立定义,继承自 Animal)
class Dog extends Animal {
// 子类重写父类方法:必须在子类内部,且加 override 关键字
override def eating(): Unit = {
//调用父类的方法?
//在子类内部通过super来访问父类
super.eating()
println("我是狗,我有自己的吃饭的方式!!")
}
}
def main(args: Array[String]): Unit = {
val dog1 = new Dog()
dog1.eating() // 输出:我是狗,我有自己的吃饭的方式!!
// 验证父类方法:创建 Animal 实例
val animal1 = new Animal()
animal1.eating() // 输出:Animal eating
}
}
多态:同一个操作,不同的结果
2.1 多态的代码实现
package level02
object class08 {
/*
* 面向对象的编程语言三大类型:封装 继承 多态
* 多态:同一个操作,作用于不同的对象,有不同的执行结果
*
*/
class Animal {
def eating(): Unit = {
println("Animal eating")
}
}
// Dog 继承了 Animal
class Dog extends Animal {
override def eating(): Unit = {
println("我是猫,我吃饭大口大口吃")
}
}
// cat 继承了 Animal
class cat extends Animal() {
override def eating(): Unit = {
println("我是猫,我吃饭大口大口吃!!")
}
}
//测试函数
//他的参数类型是 父亲
def test(animal:Animal): Unit={
animal.eating()
}
def main(args: Array[String]): Unit = {
val cat = new cat()
val dog = new Dog()
test(cat)
test(dog)
}
}
三、构造器调用顺序:父类先于子类
3.1 单层继承:父类构造器先调用
package level02
object class09 {
/*
* 继承关系的时候,构造器的调用顺序?
* 父类构造器 -> 子类构造器
*
*/
class Animal {
println("父类构造器被调用......")
}
// Dog继承了 Animal
class Dog extends Animal {
println("子类构造器被调用......")
}
//puppy 继承了 Dog
class puppy extends Dog () {
println("子类:puppy 构造器被调用......")
}
def main(args: Array[String]): Unit = {
new Dog();//new会自动调用构造器来生成对象
}
}