Scala的抽象类

67 阅读4分钟

1. 抽象类 AICar

  • 它被 abstract 修饰,因此不能直接被实例化(比如不能写 new AICar())。
  • 它的作用是 “做父类”,用来定义子类需要遵循的结构。
  • 它包含一个具体方法 autoDrive,该方法有实际的实现(打印 “具体方法,自动驾驶....”)。

2. 子类 su7

  • su7 继承自 AICar(通过 extends AICar 实现)。
  • 因为父类 AICar 中没有抽象方法(所有方法都有具体实现),所以子类 su7 可以直接继承并使用父类的方法,不需要强制重写。

3. main 方法(程序入口)

  • 首先注释了 “new AICar()” 的错误写法,体现抽象类不能直接实例化的规则。
  • 然后实例化子类 su7val su = new su7()),并调用它继承的 autoDrive 方法,最终会在控制台输出 “具体方法,自动驾驶....”。
/*
抽象类 abstract
1. 一个抽象类(加了abstract修饰的),不能被new
   一个类不能直接用来创建对象,用这个类有什么用? 做别人的父亲
2. 可以定义抽象方法,在子类中去实践
 */
  abstract class AICar {
    def autoDrive () :Unit = {
      println("具体方法,自动驾驶....")
    }
  }
  // 在子类中,一定要去实践父亲的所有抽象的方法
  class su7 extends AICar {

  }
  // 使用override 去实践这个方法
  def main(args: Array[String]): Unit = {
   // var car1 =new AICar ()
   val su = new su7()
   su.autoDrive()
  }

抽象类:定义规范的 "模板"

代码中首先定义了一个抽象类AICar,它被abstract关键字修饰,这意味着它具备两个核心特性:

  1. 不可实例化:我们无法直接通过new AICar()创建对象,因为它只是一个抽象的概念模板。

  2. 包含抽象成员:在AICar中,我们看到了两个未完成的 "约定":

    • 抽象属性val name: String:只声明了属性的名称和类型,没有具体值,相当于规定 "所有 AI 汽车必须有名称"。
    • 抽象方法def autoRun(): Unit:只定义了方法的签名,没有实现逻辑,相当于规定 "所有 AI 汽车必须具备自动驾驶功能"。

抽象类的价值正在于此 —— 它不关心具体细节,只制定子类必须遵守的 "规则",就像汽车工业的通用标准,无论哪个品牌的汽车都需要符合基本的安全规范。

子类:实现规范的 "具体产品"

为了让抽象类的规范落地,代码定义了子类xiaomi,通过extends AICar关键字继承了抽象类的所有约定。作为具体类,xiaomi必须完成抽象类中未实现的内容:

  • 实现抽象属性:为name赋值"xiaomi",明确了这是 "小米汽车"。
  • 实现抽象方法:为autoRun添加具体逻辑,打印 "小米汽车,自动驾驶....",定义了小米汽车特有的自动驾驶行为。

这里体现了继承的核心意义:子类在遵循父类规范的基础上,实现自己的具体功能。如果未来需要新增 "华为汽车" 或 "特斯拉汽车",只需创建新的子类并实现nameautoRun即可,无需修改抽象类的设计,极大提升了代码的扩展性。

程序运行:从抽象到具体的落地

main方法中,程序通过new xiaomi()实例化了xiaomi类的对象car1,并调用其autoRun方法。由于xiaomi是具体类(非抽象类),可以正常创建对象;而autoRun方法已经有了具体实现,因此最终会在控制台输出 "小米汽车,自动驾驶...."。

值得注意的是,我们无法直接实例化AICar,这正是抽象类的限制 —— 它只负责定义 "是什么" 和 "要做什么",而把 "怎么做" 的权利交给了子类。

总结:抽象类的设计思想

这段代码清晰展示了抽象类在面向对象编程中的作用:

  • 抽象与具体分离:抽象类专注于定义通用规范(抽象成员),子类专注于实现具体细节。
  • 强制规范约束:通过抽象成员确保子类必须实现关键功能,避免遗漏核心逻辑。
  • 扩展性与复用性:新增子类时只需关注自身实现,无需修改父类,符合 "开闭原则"。
下面为整体代码
/*
抽象类 abstract
1. 一个抽象类(加了abstract修饰的),不能被new
   一个类不能直接用来创建对象,用这个类有什么用? 做别人的父亲
2. 可以定义抽象方法,在子类中去实践

3. 一个抽象类中可以有:
  1.具体属性  val name:String = "xiaomi"
  2.具体方法  def autoRun():Unit = {}

  3.抽象属性  val name:String 没有具体值的属性,只有属性名和类型,它必须写在抽象类中
  4.抽象方法  def autoRun():Unit
            在子类中,要有具体的实践
 */
  abstract class AICar() {
    val name:String

    def autoRun():Unit
  }

  class xiaomi extends AICar {
    val name:String = "xiaomi"
    def autoRun():Unit = {
      println("小米汽车,自动驾驶....")
    }

  }


  def main(args: Array[String]): Unit = {
    var car1 = new xiaomi()
    car1.autoRun()

  }