★ Scala ★——继承、方法重写、抽象类、匿名类大全细则

本文详细讲解了Scala中的继承机制,如何使用抽象类和抽象方法,以及匿名内部类的使用。通过实例演示了如何创建学生和老师类的继承关系,重写方法,以及利用抽象类定义Shape和Shape的子类。同时介绍了类型判断和对象的多态性。
摘要由CSDN通过智能技术生成

★ Scala ★——方法def 与 函数 细则,99乘法表案例实现

★ Scala ★——类和对象(伴生对象)大全细则

★ Scala ★——继承、方法重写、抽象类、匿名类大全细则

★ Scala ★——Trait特质大全细则

★ Scala ★ —— 数据结构(列表、元组、数组)

★ Scala ★ —— 数据结构(集、映射、迭代器)

源码链接:https://pan.baidu.com/s/1psmnL2keRW_N781Cn-kBzg
提取码:ce34

  • 目标:
  1. 掌握继承和抽象类相关知识点
  2. 掌握匿名内部类的用法
  3. 了解类型转换的内容
  4. 掌握动物类案例

1. 继承

1.1 概述

实际开发中, 我们发现好多类中的内容是相似的(例如: 相似的属性和行为), 每次写很麻烦. 于是我们可以把这些相似的内容提取出来单独的放到一个类中(父类), 然后让那多个类(子类)和这个类(父类)产生一个关系, 从而实现子类可以访问父类的内容, 这个关系就叫: 继承。

因为scala语言是支持面向对象编程的,我们也可以使用scala来实现继承,通过继承来减少重复代码。

1.2 语法
  • scala中使用extends关键字来实现继承

  • 可以在子类中定义父类中没有的字段和方法,或者重写父类的方法

  • 类和单例对象都可以有父类

  • 语法
    class/object A类 extends B类 { .. }

  • 叫法

  • 上述格式中, A类称之为: 子类, 派生类

  • B类称之为: 父类, 超类, 基类

1.3 类继承
  • 需求
    已知学生单列对象(Student) 和老师类(Teacher), 他们都有姓名和年龄(属性), 都要吃饭(行为), 请用所学, 模拟该需求。
package Ab_extend
object ClassDemo1 {

  class Person {
    var name = ""
    var age = 0
    def eat() = println("人要吃饭!...") }

  // 2. 定义老师类.
  class Teacher extends Person

  // 3. 定义单例对象Student, 继承Person.
  object Student extends Person

  def main(args: Array[String]): Unit = {
    // 4. 测试老师类.
    val t = new Teacher
    t.name = "刘老师"
    t.age = 32
    println(s"${t.name}, ${t.age}")
    t.eat()
    println("-" * 15)

    // 5. 测试学生类.
    val s = Student
    s.name = "张三"
    s.age = 23
    println(s"${s.name}, ${s.age}")
    s.eat()
  }
}

在这里插入图片描述

2. 方法重写

2.1 概述

子类中出现和父类一模一样的方法时, 称为方法重写. Scala代码中可以在子类中使用override来重写父类的成员,也可以使用super来引用父类的成员。
注意事项

  • 子类要重写父类中的某一个方法,该方法必须要使用override关键字来修饰
  • 可以使用override来重写一个val字段.

注意: 父类用var修饰的变量, 子类不能重写。

  • 使用super关键字来访问父类的成员方法
package Ab_extend

object ClassDemo2 {

  class Person {
    var name = " "
    val age = 0

    def sayHello() = println("先Hello, Person!...")
  }

  // 2. 定义老师类,重写Person
  class Teacher extends Person{
    // override var name = "李四" //这样写会报错, 子类不能重写父类用var修饰的变量.
    override val age = 24

    override def sayHello() = {
      //通过super调用父类的成员.
      super.sayHello()
      println("Hello, Student!...")

    }
  }

  def main(args: Array[String]): Unit = {
    val t = new Teacher
    t.name = "吕布"
    println(s"${t.name}, ${t.age}")
    t.sayHello()
  }
}

在这里插入图片描述

3. 类型判断

isInstanceOf: 判断对象是否为指定类的对象
asInstanceOf: 将对象转换为指定类型

// 判断对象是否为指定类型 
val trueOrFalse:Boolean = 对象.isInstanceOf[类型] 

// 将对象转换为指定类型 
val 变量 = 对象.asInstanceOf[类型]

示例代码:
val trueOrFalse = p.isInstanceOf[Student]
val s = p.asInstanceOf[Student]
  • 案例:
  • 定义一个Person类
  • 定义一个Student类继承自Person类, 该类有一个sayHello()方法
  • 创建一个Student类对象, 并指定它的类型为Person类型
  • 判断该对象是否为Student类型,如果是,将其转换为Student类型并调用sayHello()方法
  • p.getClass可以精确获取对象的类型
  • classOf[类名]可以精确获取数据类型
  • 使用==操作符可以直接比较类型
package Ab_extend
object ClassDemo3 {

  class Person
  class Student extends Person {
    def sayHello() = println("Hello, Scala!...")
  }

  def main(args: Array[String]): Unit = {
    // 通过多态的形式创建Student类型的对象.
    val p: Person = new Student
    // s.sayHello() // 会报错, 因为多态的弊端是: 父类引用不能直接访问子类的特有成员
   
    // 判断其是否是Student类型的对象, 如果是, 将其转成Student类型的对象
    if (p.isInstanceOf[Student]) {
      val s = p.asInstanceOf[Student]
      //5. 调用Student#sayHello()方法
      s.sayHello()
    }
    println(p.getClass == classOf[Person]) // false
    // 通过getClass, ClassOf判断其是否是[..]类型的对象.
    println(p.getClass == classOf[Student]) // true
  }
}

在这里插入图片描述

4. 抽象类

scala语言是支持抽象类的, , 通过abstract关键字来实现.

4.1 定义

如果类中有抽象字段或者抽象方法, 那么该类就应该是一个抽象类

  • 抽象字段: 没有初始化值的变量就是抽象字段
  • 抽象方法: 没有方法体的方法就是一个抽象方法
// 定义抽象类 
abstract class 抽象类名 { 
	// 定义抽象字段 
	val/var 抽象字段名:类型 
	// 定义抽象方法 
	def 方法名(参数:参数类型,参数:参数类型...):返回类型 
}

在这里插入图片描述

  • 案例:
  1. 创建一个Shape抽象类,添加一个area抽象方法,name抽象字段,用于计算面积和输出。
  2. 创建一个Square正方形类,继承自Shape,它有一个边长的主构造器,并实现计算面积方法和输出名字
  3. 创建一个长方形类,继承自Shape,它有一个长、宽的主构造器,实现计算面积方法和输出名字
  4. 创建一个圆形类,继承自Shape,它有一个半径的主构造器,并实现计算面积方法和输出名字
  5. 编写main方法,分别创建正方形、长方形、圆形对象,并打印它们的面积和输出名字
package Ab_extend

// 创建形状抽象类
abstract class Shape {
  def area:Double
  var name:String
}

object ClassDemo4 {
  // 创建正方形类
  class Square(var edge:Double) extends Shape {
    // 实现父类计算面积的方法
    override def area: Double = edge * edge
    override var name: String = "正方形"
  }
  // 创建长方形类
  class Rectangle(var length:Double, var width:Double) extends Shape {
    override def area: Double = length * width
    override var name: String = "矩形"
  }

  // 创建圆形类
  class Circle(var radius:Double) extends Shape {
    override def area: Double = Math.PI * radius * radius
    override var name: String = "圆"
  }

  def main(args: Array[String]): Unit = {
    val s1:Shape = new Square(5)
    val s2:Shape = new Rectangle(4,3)
    val s3:Shape = new Circle(2)
    println(s"${s1.name}的面积是:${s1.area}")
    println(s"${s2.name}的面积是:${s2.area}")
    println(s"${s3.name}的面积是:${s3.area}")
  }
}

在这里插入图片描述

5. 匿名内部类

匿名内部类是继承了类的匿名的子类对象,它可以直接用来创建实例对象。Spark的源代码中大量使用到匿名内部类。学完这个内容, 对我们查看Spark的底层源码非常有帮助。

new 类名() { //重写类中所有的抽象内容 }
注意: 上述格式中, 如果的类的主构造器参数列表为空, 则小括号可以省略不写。

  • 使用场景
    当对对象方法(成员方法)仅调用一次的时候
    可以作为方法的参数进行传递
package Ab_extend

object ClassDemo5 {

  //1. 定义Person类, 里边有一个抽象方法: sayHello()
  abstract class Person{
    def sayHello()
  }
  //2. 定义一个show()方法, 该方法需要传入一个Person类型的对象
  def show(p:Person) = p.sayHello()

  def main(args: Array[String]): Unit = {
    // 通过匿名内部类创建Person的子类对象, 并调用sayHello()方法.
    new Person {
      override def sayHello(): Unit = println("Hello, Scala, 当对成员方法仅调用一次的时候.")
    }.sayHello()

    // 演示: 匿名内部类可以作为方法的参数进行传递
    val p = new Person {
      override def sayHello(): Unit = println("Hello, Scala, 可以作为方法的实际参数进行传递")
    }
    show(p)
  }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唐樽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值