一.本章要点

  • extends,final关键字和Java一样
  • 重写方法时必须使用override
  • 只有主构造器可以调用超类的构造器
  • 可以重写字段

二.扩展类

  Scala扩展类和Java一样(使用extends关键字),也可以将类声明为final让它不能被扩展,也可以将单个方法或字段声明为final,确保不能重写。

  注:Java中final是不可变的(相当于Scala中的val),但是Scala中是不能被扩展

三.重写方法

  使用override修饰符:

public class Person{
override def toString=....
}

  override的作用在多个常见情况下给出有用的错误提示,如:

      • 拼错重写的方法名
      • 在新方法中使用了错误的参数类型
      • 在超类中引用新的方法,但是这个方法与子类方法相抵触(易违约基类问题,超类的修改无法在不检查所有子类的前提下被验证)

  在Scala中调用超类的方法和Java完全一样,使用super关键字

四.类型检查和转换

  isInstanceOf:测试某个对象是否属于某个给定的类,可以用isInstanceOf方法,如果为true就可以用asInstanceOf方法将引用转换为子类的引用。

  例:

//如果p指向的是Employee类及其子类(比如Manager)的对象,则p.isInstanceOf[Employee]将会成功。
//如果p是null,则p.isInstanceOf[Employee]返回false,p.asInstanceOf[Employee]将返回null
//如果p不是一个Employee,则p.asInstanceOf[Employee]将抛出异常
if(p.isInstanceOf[Employee]){
val s=p.asInstanceOf[Employee] }

  classOf(在scala.Predef中,可以自动导入):测试某个对象是某个类的对象但又不是其子类。

  例:

if(p.getClass==classOf[Employee])

五.受保护字段和方法

  将字段或方法声明为protected,这样的成员可以被任何子类访问,但不能从其他位置看到。

  注:与Java不同,protected的成员对于类所属的包而言,是不可见的;  

    Scala还停工了protected[this]的变体,把访问权限限定在当前的对象

六.超类的构造

  辅助构造器永远不可能直接调用超类的构造器,子类的辅助构造器最终都会调用主构造器,只有主构造器可以调用超类的构造器。

  主类构造器和类定义交织在一起,调用超类构造器也是交织在一起。

  例:

//Employee类的三个参数有两个传递给了超类
class employee(name:String,age:Int,val salary:Double) extends Person(name,age)

  注:在Scala构造器中,不能调用super(params)[Java可以]

    Scala可以扩展Java类,这种情况必须调用Java类的某一个构造方法

七.重写字段

  子类可以重写父类的字段。

  注:

      • def只能重写另一个def
      • val只能重写另一个val或不带参数的def
      • val只能重写另一个抽象的var

  

八.匿名子类

  和Java一样,可以通过包含带有定义或重写代码块的方式创建一个匿名的子类,例:

//这会创建一个结构类型的对象,可以作为参数类型的定义
val alien=new Person("Fred"){ def greeting="xxxxxxx" } def meet(p:Person(def greeting:String)){}

九.抽象类

  和Java一样,可以用abstract关键字标记不能被实例化的类(通常因为某个或某几个方法没有被完整定义)。

  例:

 

abstract class Employee(val name:String){
def id:Int //没有方法体——抽象方法
}

  注:

    Scala中抽象方法不用使用abstract关键字,只需省略方法体就行;  

    只要类中有一个抽象方法,这个类就需要是抽象类,类必须声明abstract;  

    子类中重写超类的抽象方法时不需要使用override关键字

十.抽象字段

  即没有初始值的字段。

  例:

abstract class Person{
val id:Int //没有初始化——带有抽象的getter方法的抽象字段
var name:String //带有抽象的getter和setter方法 }

  注:子类必须提供具体的字段;

    子类重写超类的字段不需要使用override

//具体的id和name属性
class Employee(var id:Int) extends Person{
var name="" }
//通过匿名类型定制抽象字段
val fred=new Person{ val id=1
val name="Fred"
}

十一.构造顺序和提前定义

  在子类中重写val并且在超类中的构造器使用该值有可能出现问题(因为超类的构造器先于子类的构造器运行,根本原因来自Java语言的设定——允许在超类的构造方法中调用子类的方法),如:

  

class Creature{
val range:Int=10
val env:Array[Int] = new Array[Int](range) } class Ant extends Creature{
override val range=2 }
......
//长度为0
val ant=new Ant
println(ant.env.length)
/××
过程如下:
1.Ant的构造器在构造自己之前先调用Creature的构造器;
2.Creature的构造器把它的range设为10;
3.Creature的构造器为了初始化env数组,调用range()取值器;
4.该方法被重写以输出(还未初始化)Ant类的range字段值;
5.range方法返回0(这是对象被分配空间时所有整型字段的初始值);
6.env被设为长度为0的数组;
7.Ant构造器继续执行,将其range设为2
××/

  注:因此构造器内不应该依赖val的值;

    解决方式:

      1.将val声明为final,这样很安全但并不灵活;

      2.在超类中将val声明为lazy,这样很安全但不高效;

      3.在子类中使用提前定义方法(可以在超类的构造器执行之前初始化子类的val字段),使用with关键字(提前定义的等号右侧只能引用之前已有的提前定义,而不能使用类中的其他字段或方法)

class Ant extends{
override val range=2 }with Creature

    可以使用-Xcheckinit编译器标志调式构造顺序    

十二.Scala继承等级

Scala继承等级

  注:

    AnyRef是Java或.Net虚拟机Object类的同义词;

    AnyVal和AnyRef都扩展于Any类,而Any类是整个继承等级的根节点;

    Any类中定义了isInstanceOf,asInstanceOf方法,相等性判断,哈希码的方法;

    AnyVal没有追加任何方法,他只是一个标记;

    AnyRef追加了来自Object类的监视方法wait和notify/notifyAll,同时提供了synchronized方法;

    所有Scala类都实现ScalaObject这个标记接口,该接口没有任何方法;

    Null值的唯一实例是null;

    Nothing类型没有实例  

十三.对象相等性

  Scala中AnyRef的eq方法检查两个引用是否指向同一个对象,AnyRef的equals方法调用eq。

  实现类的时候有需要时重写equals根据自己的逻辑判断,例:

  注:将方法定义为final,因为通常而言在子类中正确扩展相等性判断非常困难;

    确保定义的equals方法参数类型为Any ;

    再定义equals时,记得同时定义hashCode 

final override def equals(other:Any){

val that=other.asInstanceOf(Item)
if(that==null) false
else description==that.description&&price==that.price
}

  

十四.练习

Scala学习八——继承的更多相关文章

  1. Scala学习(八)---Scala继承

    Scala继承 摘要: 在本篇中,你将了解到Scala的继承与Java和C++最显著的不同.要点包括: 1. extends.final关键字和Java中相同 2. 重写方法时必须用override ...

  2. Scala学习(八)练习

    Scala中继承&练习 1. 扩展如下的BankAccount类,新类CheckingAccount对每次存款和取款都收取1美元的手续费 class BankAccount ( initial ...

  3. JavaScript之面向对象学习八(继承)

    简介:继承是OO语言中的一个最为人津津乐道的概念.许多OO语言都支持两种继承方式:接口继承和实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法. 但是JS的函数并没有签名,所以在ECMASc ...

  4. scala学习笔记2(类,继承,抽象类)

    class Person{ // _ 是占位符; var name : String = _ val age : Int = 27 // private[this] 定义的内容无法外部使用,起到保护作 ...

  5. (C/C++学习笔记) 十八. 继承和多态

    十八. 继承和多态 ● 继承的概念 继承(inheritance): 以旧类为基础创建新类, 新类包含了旧类的数据成员和成员函数(除了构造函数和析构函数), 并且可以派生类中定义新成员. 形式: cl ...

  6. Scala 学习之路(九)—— 继承和特质

    一.继承 1.1 Scala中的继承结构 Scala中继承关系如下图: Any是整个继承关系的根节点: AnyRef包含Scala Classes和Java Classes,等价于Java中的java ...

  7. 【Todo】【读书笔记】大数据Spark企业级实战版 & Scala学习

    下了这本<大数据Spark企业级实战版>, 另外还有一本<Spark大数据处理:技术.应用与性能优化(全)> 先看前一篇. 根据书里的前言里面,对于阅读顺序的建议.先看最后的S ...

  8. Python Tutorial 学习(八)--Errors and Exceptions

    Python Tutorial 学习(八)--Errors and Exceptions恢复 Errors and Exceptions 错误与异常 此前,我们还没有开始着眼于错误信息.不过如果你是一 ...

  9. 【大数据】Scala学习笔记

    第 1 章 scala的概述1 1.1 学习sdala的原因 1 1.2 Scala语言诞生小故事 1 1.3 Scala 和 Java  以及 jvm 的关系分析图 2 1.4 Scala语言的特点 ...

随机推荐

  1. svg简单的应用

    1.可以直接在html内写svg (1)width宽度,height高度 (2)xmlns svg的规则 <svg xmlns="http://www.w3.org/2000/svg& ...

  2. ansible的错误

    错误 [root@bogon ansible]# ansible test -m ping 192.168.16.155 | FAILED! => { "msg": &quo ...

  3. 性能测试 | Linux系统top命令中的io使用率,很多人都误解了它的具体含义

    body{ text-align:left; width:80%; margin:10px 100px; } 最近在做连续数据流的缓冲系统,C语言代码实现后,粗略测试了下,功能上应该没有问题.那么,接 ...

  4. SpringCloud(2)----SpringCloud理解篇

    一.微服务概述 1.什么是微服务 目前的微服务并没有一个统一的标准,一般是以业务来划分将传统的一站式应用,拆分成一个个的服务,彻底去耦合,一个微服务就是单功能业务,只做一件事. 与微服务相对的叫巨石 ...

  5. Mac下安装brew

    1.Mac 终端下,执行以下命令,即可安装brew: /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Hom ...

  6. Android视频直播全屏实现

    /** * 添加直播组件 */ @SuppressLint("JavascriptInterface") private void addPlayerLive(final Subj ...

  7. h5 与原生 app 交互的原理

    现在移动端 web 应用,很多时候都需要与原生 app 进行交互.沟通(运行在 webview中),比如微信的 jssdk,通过 window.wx 对象调用一些原生 app 的功能.所以,这次就来捋 ...

  8. How To Install OpenSSL on Windows

    转自 https://tecadmin.net/install-openssl-on-windows/ OpenSSL is a full-featured toolkit for the Trans ...

  9. PHP yii2.0框架利用mpdf导出pdf

    安装: composer require mpdf/mpdf 使用: use Mpdf\Mpdf;//(php7以前) //获取页面内容 $res = $this->controller-> ...

  10. COALESCE关键字的使用

    COALESCE是sql标准里面的一个关键字,我们可以和聚合函数sum,count,max等一起使用完成一些特殊的功能. 以下sql语句基于mysql 1.查询某一个列总和,如果没有数据或者NULL返 ...