scala基础5 —— 类的继承

本文探讨了Scala中的类继承,包括extends关键字、final修饰符、构造函数、访问控制、重写、抽象类和继承层次。详细阐述了如何使用final修饰类成员,如何定义构造函数以及如何调用父类构造器。此外,还介绍了protected访问控制和override关键字在重写中的应用,以及抽象类的定义和使用。最后,文章讲解了类型检查与转换的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

面向对象语言很重要的一个特点就是继承,我们来看看scala语言的继承有哪些特点。

extends关键字

首先,scala继承类的关键字和java一样,都是extends,比如:

class Person {
  var name : String = ""
}
class Man extends Person { // Man继承自Person
  var sex : Int = 0
} 
}

final关键字的使用:

  1. 不想让类被继承,可以声明为final,这和java一样;
  2. 可以将类某一个字段或方法声明为final,表明不可被重写,这和java不一样,java中final变量相当于scala的val;
    比如:
final class Person {
  var name : String = ""
}
class Man extends Person { //error 编译时illegal inheritance from final class Person
  var sex : Int = 0
}

构造函数

由于scala的构造函数有主构造函数和辅助构造函数,我们知道scala的辅助构造函数必须以对主构造函数或之前定义的辅助构造函数开始,因此,辅助构造函数无法直接调用父类的构造函数,那如何构造父类部分呢?答案是通过主构造函数。如果父类主构造器没有参数,则都是默认值,如果父类主构造器有参数,则必须在子类主构造器中指定参数。比如:

class Person (var name : String, var age : Int) () {
    // body
}
class Student (var manName : String, var manAge : Int, var school : String) extends Person(manName, manAge) {
    // body
}

在java中,一般是通过在构造函数中调用super来调用父类构造函数,在scala中,主构造器不能使用super方式,但是父类的普通函数依然可以通过super来调用,比如:

class Person (var name : String, var age : Int) () {
  def print = name + " :" + age
}
class Student (var manName : String, var manAge : Int, var school : String) extends Person(manName, manAge) {
  override def print = super.toString + ":" + school // 可以通过super来调用普通函数
}

访问控制

同java一样,我们可以将方法和字段声明为protected,这样字段或方法只能被任何子类访问,其他地方不可访问。
这个protected和java的不太一样,另,还有一个protected[this]可以将访问权限控制在当前对象。

重写

  1. scala可以重写父类方法,但需要override关键字,类似于java中可选的@Override注解,如上例中Student类重写print方法,需要override关键字。
  2. scala和java不一样的是,也可以重写字段。那val,var和不带参数的def之间的重写什么规则呢。
重写字段用val重写用var重写用def重写
val字段可以,子类有一个同名字段不可以不可以
var字段不可以仅当父类的var字段是抽象的才可以不可以
def无参函数可以,子类有一个字段和对应getter重写父类方法可以,需重写getter和setter对可以,同重写函数

抽象类

  1. scala也可以使用abstract关键字将类声明为抽象类,但是关键字不能用于方法。
  2. 抽象类也可以有抽象字段,即没有初始化的字段,子类必须提供具体的字段。
    比如:
abstract class Person {
  val name : String  // 抽象val字段
  var age : Int  // 抽象var字段
  def print  // 抽象函数
}

class Student extends Person {
  val name = "name" // 不需要override字段
  var age = 10 // 不需要override字段
  def print = name + ":" + age // 不需要override字段
}

scala类继承层次

scala类的继承层次如下图所示:
这里写图片描述
基本类型以及Unit类型,都继承自AnyVal,AnyRef和java的Object对应,是所有对象类的基类。而他们都继承自Any类,继承层次跟节点。
Any类定义了isInstanceOf、asInstanceOf、equals、hashCode等,AnyRef额外定义了Object类的监视方法wait、notify和notifyAll,同时提供synchronized方法(等同于java的synchronized块)。

类型检查和转换

其中isInstanceOf用来判断对象是否是某个类,asInstanceOf方法将引用转换为子类的引用,比如:

    val x = 1
    var ret = if (x.isInstanceOf[Int]) {
      x.asInstanceOf[Int] + 1
    } else if (x.isInstanceOf[Long]) {
      x.asInstanceOf[Long]
    } else {
      -1
    }

类型检查和类型匹配,可以使用match,这样效果更好,比如上面的可以改为:

    val x = 1
    var ret = x match {
      case i : Int => i + 1
      case l : Long => l
      case _ => -1
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值