(一)继承的概念和基本语法
❤️定义:在原有类的基础上定义一个新类,原有类称为父类,新类称为子类。
class 子类名 extends 父类名 { 类体 }
💖好处: 复用代码和实现多态。
💖复用代码:子类可以继承父类的特性。
💖多态:子类可以在自己内部实现父类没有的特性。
💖假设定义Parents为父类,C1为子类,通过关键字extends子类便可以继承父类的特性,相关代码为:
class C1(参数可选) extends Parents(参数可选){ }
(二)继承的好处之复用代码
💥一旦我们完成了继承,就可以直接在子类的对象中调用父类的方法。
💥继承的特点:Dog就直接具备了animal的功能eating。
(三)继承的方法重写
💕问:当子类从父类继承的方法不能满足需要时,子类需要有自己的行为,怎么办?
💕答:此时使用使用 override 可以重写父类的方法。
格式:
override def 方法名(参数可选) { }
object r1104 {
/*继承
extends
好处:不劳而获*/
class Animal() {
def eating():Unit = {
println("Animal eating")
}
}
//Dog继承了Animal
class Dog extends Animal(){
//在子类中重写(覆盖)父类的方法
override def eating(): Unit = {
println("我是狗 我有自己吃饭的方式!")
}
}
def main(args: Array[String]): Unit = {
val dog1 = new Dog()
dog1.eating()// 调用自己的eating方法!
}
//运行结果:
我是狗 我有自己吃饭的方式!
(四)定义自己的方法
问题:如果子类觉得父类的方法并不是自己要的 如何定义自己的方法呢?
1.overrride 重写。
2.super 在子类内部 通过super来访问父类。
object r1104 {
/*继承
extends
好处:不劳而获
问题:如果子类觉得父类的方法并不是自己要的 如何定义自己的方法呢?
1.overrride 重写
2.super 在子类内部 通过super来访问父类
*/
class Animal() {
def eating():Unit = {
println("Animal eating")
}
}
//Dog继承了Animal
class Dog extends Animal(){
//在子类中重写(覆盖)父类的方法
override def eating(): Unit = {
//调用父类方法?
//在子类内部 通过super来访问父类
super.eating()
println("我是狗 我有自己吃饭的方式!")
}
}
def main(args: Array[String]): Unit = {
val dog1 = new Dog()
dog1.eating()// 调用自己的eating方法!
}
//运行结果:
Animal eating
我是狗 我有自己吃饭的方式!
(五)继承与多态
-
面向对象的三个特点:封装 继承 多态 。
-
多态:同一操作作用于不同的对象, 可以有不同的解释,产生不同的执行结果。
-
通过代码来理解多态写一个函数,它的参数类型是
父类。
//面向对象的编程语言有三大特性:封装 继承 多态
//多态:同一个操作 作用于不同对象 有不同的执行结果。
object y1104 {
class Animal() {
def eating():Unit = {
println("Animal eating")
}
}
//Dog继承了Animal
class Dog extends Animal(){
//在子类中重写(覆盖)父类的方法
override def eating(): Unit = {
//调用父类方法?
//在子类内部 通过super来访问父类
super.eating()
println("我是狗 我吃饭大口大口吃!")
}
}
//Cat继承了Animal
class Cat extends Animal(){
//在子类中重写(覆盖)父类的方法
override def eating(): Unit = {
//调用父类方法?
//在子类内部 通过super来访问父类
super.eating()
println("我是猫 我吃饭小口小口吃!")
}
}
//测试函数
//它的参数类型是 父类
def test(animal: Animal): Unit = {
animal.eating()
}
def main(args: Array[String]): Unit = {
val dog = new Dog()
val cat= new Cat()
//传入子类的对象
test(dog)
test(cat)
}
//运行结果:
Animal eating
我是狗 我吃饭大口大口吃!
Animal eating
我是猫 我吃饭小口小口吃!
(六)处理构造器的调用顺序
💕调用顺序:父类的主构造器 -> 子类主构造器 -> 子类的辅助构造器
/*存在继承关系的时候 构造器的调用顺序?
父类构造器 → 子类构造器*/
object w1104 {
class Animal() {
println("父类构造器被调用")
}
//Cat继承了Animal
class Dog extends Animal(){
println("子类:Dog构造器被调用")
}
//Puppy继承了Dog
class Puppy extends Dog(){
println("子类:Puppy构造器被调用")
}
def main(args: Array[String]): Unit = {
new Puppy(); //new会自动调用构造器去生成对象
}
//运行结果:
父类构造器被调用
子类:Dog构造器被调用
子类:Puppy构造器被调用