scala_继承、类型判断、抽象类、匿名内部类

本文详细介绍了Scala中的继承机制,包括类继承和单例对象继承,以及`override`和`super`的使用。同时,讨论了类型判断的方法,如`isInstanceOf`、`asInstanceOf`、`getClass`和`classOf`。此外,文章还讲解了抽象类的概念,包括抽象方法和抽象字段的定义与示例。最后,提到了匿名内部类的定义和使用场景。
摘要由CSDN通过智能技术生成

继承

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

定义语法

  • scala和Java一样,使用extends关键字来实现继承
  • 可以在子类中定义父类中没有的字段和方法,或者重写父类的方法
  • 类和单例对象都可以从某个父类继承

语法

class/object 子类 extends 父类 {
    ..
}

示例 | 类继承

  • 定义一个Person类,再定义一个Student类,继承自Person类

在这里插入图片描述

  • 创建一个Student类对象实例,并设置name为“张三”

  • 打印姓名

参考代码

class Person {
  var name = "super"

  def getName = this.name
}

class Student extends Person

object Main13 {
  def main(args: Array[String]): Unit = {
    val p1 = new Person()
    val p2 = new Student()

    p2.name = "张三"

    println(p2.getName)
  }
}

示例 | 单例对象继承

示例说明

  • 创建一个Student单例对象,让单例对象继承示例1中的Person类
  • 设置单例对象的名字为"张三",调用Student单例对象的getName方法
class Person {
  var name = "super"

  def getName = this.name
}

object Student extends Person

object Main13 {
  def main(args: Array[String]): Unit = {

    println(Student.getName)
  }
}

override和super

类似于Java语言,我们在子类中使用override需要来重写父类的成员,可以使用super来引用父类

用法

  • 子类要覆盖父类中的一个方法,必须要使用override关键字
  • 使用override来重写一个val字段
  • 使用super关键字来访问父类的成员方法

示例

示例说明

  • 定义一个Person类,包含
    • 姓名字段(不可重新赋值)
    • 获取姓名方法
  • 定义一个Student类
    • 重写姓名字段
    • 重写获取姓名方法,返回"hello, " + 姓名
  • 创建Student对象示例,调用它的getName方法

参考代码

class Person {
  val name = "super"

  def getName = name
}

class Student extends Person {
  // 重写val字段
  override val name: String = "child"

  // 重写getName方法
  override def getName: String = "hello, " + super.getName
}

object Main13 {
  def main(args: Array[String]): Unit = {
    println(new Student().getName)
  }
}

类型判断

有时候,我们设计的程序,要根据变量的类型来执行对应的逻辑。

在这里插入图片描述

在scala中,如何来进行类型判断呢?

有两种方式:

  • isInstanceOf
  • getClass/classOf

isInstanceOf/asInstanceOf

在Java中,我们可以使用instanceof关键字来判断类型、以及(类型)object来进行类型转换,在scala中如何实现呢?


scala中对象提供isInstanceOf和asInstanceOf方法。

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

用法

// 判断对象是否为指定类型
val trueOrFalse:Boolean = 对象.isInstanceOf[类型]
// 将对象转换为指定类型
val 变量 = 对象.asInstanceOf[类型]

示例

示例说明

  • 定义一个Person类
  • 定义一个Student类继承自Person类
  • 创建一个Student类对象
  • 判断该对象是否为Student类型,如果是,将其转换为Student类型并打印该对象

参考代码

class Person3
class Student3 extends Person3

object Main3 {
  def main(args: Array[String]): Unit = {
    val s1:Person3 = new Student3

    // 判断s1是否为Student3类型
    if(s1.isInstanceOf[Student3]) {
      // 将s1转换为Student3类型
      val s2 =  s1.asInstanceOf[Student3]
      println(s2)
    }

  }
}

getClass和classOf

isInstanceOf 只能判断对象是否为指定类以及其子类的对象,而不能精确的判断出,对象就是指定类的对象。如果要求精确地判断出对象就是指定类的对象,那么就只能使用 getClass 和 classOf 。

用法

  • p.getClass可以精确获取对象的类型
  • classOf[x]可以精确获取类型
  • 使用==操作符可以直接比较类型

示例

示例说明

  • 定义一个Person类
  • 定义一个Student类继承自Person类
  • 创建一个Student类对象,并指定它的类型为Person类型
  • 测试使用isInstance判断该对象是否为Person类型
  • 测试使用getClass/classOf判断该对象是否为Person类型
  • 测试使用getClass/classOf判断该对象是否为Student类型

参考代码

class Person4
class Student4 extends Person4

object Student4{
  def main(args: Array[String]) {
    val p:Person4=new Student4
    //判断p是否为Person4类的实例
    println(p.isInstanceOf[Person4])//true

    //判断p的类型是否为Person4类
    println(p.getClass == classOf[Person4])//false

    //判断p的类型是否为Student4类
    println(p.getClass == classOf[Student4])//true
  }
}

抽象类

和Java语言一样,scala中也可以定义抽象类

定义

如果类的某个成员在当前类中的定义是不包含完整的,它就是一个抽象类

不完整定义有两种情况:

  1. 方法没有方法体(抽象方法
  2. 变量没有初始化(抽象字段

定义抽象类和Java一样,在类前面加上abstract关键字

// 定义抽象类
abstract class 抽象类名 {
  // 定义抽象字段
  val 抽象字段名:类型
  // 定义抽象方法
  def 方法名(参数:参数类型,参数:参数类型...):返回类型
}

抽象方法

示例

在这里插入图片描述

  • 设计4个类,表示上述图中的继承关系
  • 每一个形状都有自己求面积的方法,但是不同的形状计算面积的方法不同

步骤

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

参考代码

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

// 创建正方形类
class Square(var edge:Double /*边长*/) extends Shape {
  // 实现父类计算面积的方法
  override def area: Double = edge * edge
}

// 创建长方形类
class Rectangle(var length:Double /*长*/, var width:Double /*宽*/) extends Shape {
  override def area: Double = length * width
}

// 创建圆形类
class Cirle(var radius:Double /*半径*/) extends Shape {
  override def area: Double = Math.PI * radius * radius
}

object Main6 {
  def main(args: Array[String]): Unit = {
    val s1:Shape = new Square(2)
    val s2:Shape = new Rectangle(2,3)
    val s3:Shape = new Cirle(2)

    println(s1.area)
    println(s2.area)
    println(s3.area)
  }
}

抽象字段

在scala中,也可以定义抽象的字段。如果一个成员变量是没有初始化,我们就认为它是抽象的。

定义

语法

abstract class 抽象类 {
    val/var 抽象字段:类型
}

示例

示例说明

  1. 创建一个Person抽象类,它有一个String抽象字段WHO_AM_I
  2. 创建一个Student类,继承自Person类,重写WHO_AM_I字段,初始化为学生
  3. 创建一个Policeman类,继承自Person类,重写WHO_AM_I字段,初始化警察
  4. 添加main方法,分别创建Student/Policeman的实例,然后分别打印WHO_AM_I

参考代码

// 定义一个人的抽象类
abstract class Person6 {
  // 没有初始化的val字段就是抽象字段
  val WHO_AM_I:String
}

class Student6 extends Person6 {
  override val WHO_AM_I: String = "学生"
}

class Policeman6 extends Person6 {
  override val WHO_AM_I: String = "警察"
}

object Main6 {
  def main(args: Array[String]): Unit = {
    val p1 = new Student6
    val p2 = new Policeman6

    println(p1.WHO_AM_I)
    println(p2.WHO_AM_I)
  }
}

匿名内部类

匿名内部类是没有名称的子类,直接用来创建实例对象。Spark的源代码中有大量使用到匿名内部类。

scala中的匿名内部类使用与Java一致。

定义

语法

val/var 变量名 = new 类/抽象类 {
    // 重写方法
}

示例

示例说明

  1. 创建一个Person抽象类,并添加一个sayHello抽象方法
  2. 添加main方法,通过创建匿名内部类的方式来实现Person
  3. 调用匿名内部类对象的sayHello方法

参考代码

abstract class Person7 {
  def sayHello:Unit
}

object Main7 {
  def main(args: Array[String]): Unit = {
    // 直接用new来创建一个匿名内部类对象
    val p1 = new Person7 {
      override def sayHello: Unit = println("我是一个匿名内部类")
    }
    p1.sayHello
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值