类的继承

91 阅读3分钟

一、继承的概念和基本语法

定义:在原有类的基础上定义一个新类,原有类称为父类,新类称为子类。

class 子类名 extends 父类名 { 类体 }

语法:假设定义Parents为父类,C1为子类,通过关键字extends子类便可以继承父类的特性,相关代码为:

class C1(参数可选) extends Parents(参数可选){ }

二、继承的好处

一旦我们完成了继承,就可以直接在子类的对象中调用父类的方法。

继承的特点:Dog就直接具备了animal的功能eating。

屏幕截图 2025-11-16 163051.png

/*
  1.多个类
  2.继承
    class 子类 extends 父类
  3.好处:不劳而获。子类可以直接使用父类的属性和方法
 */

object class10 {
  // 动物
  class Animal(var name:String="动物") {
    val age:Int=10
    def eat(): Unit={
      println("animal eat")
    }
    def run():Unit={
      println("amimal run")
    }
  }

  // 狗
  class Dog() extends Animal(){

  }

  def main(args: Array[String]): Unit = {
    val d1=new Dog()
    d1.eat()
    d1.run()
  }
}

三、继承的方法重写

格式:

override def 方法名(参数可选) { }

/*
  1.多个类
  2.继承
    class 子类 extends 父类
  3.好处:不劳而获。子类可以直接使用父类的属性和方法
  4.子类对父类的方法的重写
    在子类中,通过override 覆盖(重写)父类的同名方法
  5.super. 在子类中访问父亲
 */

object class11 {
  class Parent() {
    val name:String=""
    def run():Unit={
      println("run")
    }
  }

  class son() extends Parent(){
    // 如果希望对父类的方法进行改进:觉得不好
    def run1():Unit={
    }
    override def run():Unit={
      super.run() // super.run 在子类中,调用父亲的方法
      println("开自动驾驶的车 run")
    }
  }

  def main(args: Array[String]): Unit = {
    val s1=new son()
    s1.run()
  }
}

四、继承与多态

面向对象的三个特点封装,继承_ ,__ 多态 __ 。同一操作作用于不同的对象, 可以有不同的解释,产生不同的执行结果,这就是多态性。

/*
  1.多个类
  2.继承
    class 子类 extends 父类
  3.好处:不劳而获。子类可以直接使用父类的属性和方法
  4.子类对父类的方法的重写
    在子类中,通过override 覆盖(重写)父类的同名方法
  5.super. 在子类中访问父亲
  6.面向对象编程的三大特征:封装,__继承____,__多态__

 */

object class12 {
  class Fruit() {
    def eat():Unit={
      println("eat")
    }
  }

  class Apple extends Fruit{
    override def eat():Unit={
      println("吃掉果皮,中间的不能吃")
    }
  }

  class Watermelon extends Fruit{
    override def eat():Unit={
      println("削皮,中间的最好吃")
    }
  }

  def main(args: Array[String]): Unit = {
    // 参数类型:父亲
    def test(fruit: Fruit):Unit={
      fruit.eat()
    }
    val a1=new Apple()
    test(a1) // 传入子类

    val w1=new Watermelon()
    test(w1)
  }
}

屏幕截图 2025-11-10 093232.png

五、构造器的调用顺序

代码验证调用顺序:父类的构造器->子类构造器

7.构造器的调用顺序:先调用父类的,再调用子类的
 */

object class13 {
  class Father() {
    println("Father的构造器")
  }
  class son extends Father(){
    println("son的构造器")
  }

  def main(args: Array[String]): Unit = {
    // 创建一个子类对象时,
    // 先调用父类的构造器→子类的构造器
    new son()
  }
}

六、带参构造器的写法

1. 父类构造器正常写。

2. 在写子类构造器时:

(1)如果某个属性可以从父类中继承过来,那么这些属性就不要添加任何的修饰符(val,var都不加)如果这属性是子类自己特有的,就需要补充修饰符;

(2)在父类构造器时,直接传入对应的参数。


8.当父类,子类都存在带参数的构造器时,如何进行参数传递

 */

object class14 {
  // 父类
  class Animal(var name:String,var age:Int) {
    println(s"父类的构造器被调用....${name},${age}")
    def say():Unit={
      println(s"Animal ${name},${age}")
    }
  }

  // 子类
  class Dog(name:String,age:Int,var color:String) extends Animal(name, age){
    println(s"子类的构造器被调用....${name},${age},${color}")
    override def say():Unit={
      super.say()
      println(s"狗狗....,我的颜色是${color}")
    }
  }

  def main(args: Array[String]): Unit = {
    val d1=new Dog("旺财",1,"黑色")
    d1.say()
  }
}