1. 继承

Scala 通过 extends 关键字来继承类.

那么继承一个类有什么好处呢?

  1. 子类拥有继承自超类的方法和字段(即为val(常量), var(变量)所定义的)
  2. 可以添加自己需要的新方法和新字段,
  3. 不但可以重写超类的方法, 还可以重写超类的字段.

final 关键字

Scala 中, 不仅可以将类声明为 final, 而且可以将字段和方法声明为 final

当类被声明为 final 时, 类不可以被继承; 当方法和字段被声明为 final 时, 对应的方法和字段不可以被子类重写, 看看下面这个例子就一目了然

  1. class Person {
  2. final val name = "person"
  3. val age = 1
  4. }
  5. class Kid extends Person {
  6. // 报错: Value 'name' can not override final member
  7. // override val name = "jerry"
  8. override val age = 2
  9. }
  10. object test extends App {
  11. val k = new Kid;
  12. println(k.age) // 2
  13. }

2. 重写方法

在 Scala 中重写一个 非抽象方法 必须使用 override 修饰符, 如:

  1. override def toString: String = getClass.getName + "[name=" + name + "]"

override修饰符可以在多个常见的情况下给出有用的错误提示, 包括:

  1. 当你拼错了要重写的方法名和字段名
  2. 当你不小心在新方法中使用了错误的参数类型
  3. 当你在超类中引入了新方法, 而这个新方法和子类的方法抵触

Scala 使用 super 关键字调用超类的方法, super.toString 相当于 Person.toString

  1. class Person {
  2. val name = "person"
  3. val age = 1
  4. override def toString: String = getClass.getName + "[name=" + name + "]"
  5. }
  6. class Kid extends Person {
  7. override val name = "kid"
  8. override val age = 2
  9. override def toString: String = super.toString + "[age=" + age + "]"
  10. }
  11. object test extends App {
  12. val person = new Kid;
  13. println(person.age) // 2
  14. println(person) // chap08.Kid[name=kid][age=2]
  15. }

3. 类型检查和转换

Scala语言中可以使用 isInstanceOf[T] 方法, 测试某个对象实际类型是否属于某个给定类T或者类T的子类; 测试成功之后可以用 asInstanceOf[T] 方法将对象引用转化为的(子类)类T引用(一般来说对象的引用类型是T的父类, 而实际类型是T或者T的子类)

  1. if (person.isInstanceOf[Kid]) {
  2. val k = person.asInstanceOf[Kid]
  3. }

如果 person 是null, 则 person.isInstanceOf[Kid] 返回false, kid.asInstanceOf[Kid] 返回null;

如果 person 不是一个 Kid, kid.asInstanceOf[Kid]将抛出异常

如果要测试 person 指向Kid类又不是其子类, 使用如下方法:

  1. if (person.getClass == classOf[Kid]) {
  2. val s = person.asInstanceOf[Kid]
  3. }

4. 超类构造

类有一个主构造器和任意数量的辅助构造器, 而每个辅助构造器都必须以对先前定义的辅助构造器或者主构造器的调用开始, 这样做的结果就是:

辅助构造器永远都不可能直接调用超类的构造器; 子类的辅助构造器最终都会调用主构造器; 只有主构造器而已调用超类的构造器.

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

  1. class Kid(gender: String, val height: Double) extends Person(gender)

Kid类有2个参数, 一个被"传递"到超类

scala语言的(主)构造器中, 你不能调用super(paras)

5. 重写字段

Scala 的字段(Fields)是指 一个 var或者val 定义的变量(或值)和对应的getter/setter 方法

你可以用一个同名的val字段重写一个val或者不带参数的def, 子类有一个私有字段和一个共有的getter方法, 而这个getter方法重写了超类的getter方法.

  1. class Smiler(val happy: String) {
  2. override def toString: String = getClass.getName + "[happy: " + happy + "]"
  3. }
  4. class Laughter(veryhappy: String) extends Smiler(veryhappy) {
  5. override val happy: String = "Laughter"
  6. override val toString: String = super.toString
  7. }

更常见的例子是 val 重写抽象的 def,就像这样:

  1. abstract class Smiler(val happy: String) {
  2. def degree: Int
  3. }
  4. class Laughter(h: String, override val degree: Int) extends Smiler(h) {
  5. }

注意如下限制:

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

6. 匿名子类

你可以通过包含带有定义或重写的代码块的方式创建一个匿名子类,比如

  1. val alien = new Person("good") {
  2. def greeting = "hi, good"
  3. }

7. 抽象类与抽象字段

  • 不需要对抽象方法和抽象字段用 abstract 关键字
  • 子类中重写超类的抽象方法和抽象字段时, 可以不写 override 关键字, 不过 scala in depth 一书分析了总是使用 override 关键字会带来更多的好处, 那就加上吧
  • 只要类中存在抽象方法, 该类必须声明为 abstract

7.1 抽象类

Scala 中使用 abstract 关键字来标记不能实例化的类, 通常是因为它的某个或者几个方法没有完整定义. 例如

  1. abstract class Smiler(val happy: String) {
  2. def degree: Int
  3. }
  • 在Scala中, 不需要对抽象方法用 abstract 关键字, 只是省去其方法体
  • 只要类中存在抽象方法, 该类必须声明为 abstract
  • 子类重写超类的抽象方法时, 不需要 override 关键字
  1. class Laughter(h: String) extends Smiler(h) {
  2. def degree = h.hashCode
  3. }

7.2 抽象字段

除了抽象方法外, 类还可以有抽象字段; 抽象字段就是一个没有初始值的字段. 具体的子类必须提供具体的字段; 和方法一样, 子类中重写超类的抽象字段时, 不需要override关键字

  1. abstract class Abstract {
  2. val id: Int // 没有初始化, 这是一个带有getter方法的抽象字段
  3. var name: String // 没有初始化, 这是一个带有getter和setting方法的抽象字段
  4. }
  5. class AbstractField(val id: Int) extends Abstract {
  6. var name = getClass.getName // override 可选
  7. }

可以随时用匿名类型来定制抽象字段

  1. val laught = new Abstract {
  2. val id = 10
  3. var name = "laught"
  4. }

8. Scala继承层级

  1. 与Java基本类型相对应的类以及Unit类型(相当于Java的void)都扩展自AnyVal
  2. 所有其他类都是AnyRef的子类, Any是整个继承层级的根节点, AnyVal和AnyRef扩展自Any类
  3. Any类定义了isInstanceOf asInstanceOf方法, 以及用于相等性判断和哈希码方法, AnyVal并没有追加方法, 只是所有值类型的一个标记
  4. Null类型唯一的实例就是null, 你可以将null赋值给任何引用, 但不能赋值给值类型的变量, 举例来说不能讲Int赋值为null
  5. Nothing类型没有实例, 它对于泛型结构很有用, 比如说空列表Nil是List[Nothing], 它是List[T]的子类型, T可以是任何类型

Scala中的Nothing类型和Java中void不是一个概念;

Scala中void由Unit类型表示, 该类型只有一个值, 那就是();

<<快学Scala>> 中所说虽然Unit不是任何类型的超类, 但编译器允许任何值来替换成(), 不过现在测试scala2.12.2, Scala已经修改这个语法, 现在不管传入什么值, printUnit的输出结果都是()

  1. def printAny(x: Any) {print(x)}
  2. def printUnit(x: Unit) {print(x)}
  3. printAny("happy")
  4. printUnit("happy")
  5. /*output:
  6. happy
  7. ()
  8. /*

9. 对象相等性

Scala中调用 ==, 如果比较的是引用类型, Scala会先做null检查, 然后调用equals 方法



Scala 继承的更多相关文章

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

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

  2. 7.scala:继承

    版权申明:转载请注明出处. 文章来源:http://bigdataer.net/?p=315 排版乱?请移步原文获得更好的阅读体验 类似于java中的继承,在scala中同样有继承一说,而且在很多方面 ...

  3. Scala继承

    override重写 为什么要用override关键字?因为这样更清楚,不容易出错,比如打错字了,就没覆盖成功,但是不会报错 override可以覆盖feild和method class Person ...

  4. Scala实战高手****第10课:Scala继承彻底实战和Spark源码鉴赏

    isInstanceOf  和 asInstanceOf is用于判断 as用于转换,把父类类型转换成子类类型   getClass 具体找出类型    

  5. 快学Scala之继承

        ## 1. 继承 Scala语言通过 extends 关键字来继承类. 那么继承一个类有什么好处呢? 子类除了拥有继承自超类的方法和字段(即为val(常量), var(变量)所定义的), 还可 ...

  6. Scala学习八——继承

    一.本章要点 extends,final关键字和Java一样 重写方法时必须使用override 只有主构造器可以调用超类的构造器 可以重写字段 二.扩展类 Scala扩展类和Java一样(使用ext ...

  7. Scala 面向对象(六):面向对象的特征二:继承 (一)

    1 Scala继承的基本语法 class 子类名 extends 父类名 { 类体 } class Person { var name : String = _ var age : Int = _ d ...

  8. [Scala] 快学Scala A1L1

    基础 1.1 声明值和变量 在Scala中,鼓励使用val; 不需要给出值或变量的类型,这个信息可以从初始化表达式推断出来.在必要的时候,可以指定类型. 在Scala中,仅当同一行代码中存在多条语句时 ...

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

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

随机推荐

  1. nginx配置模板问题404

    nginx配置模板问题 一.nginx主配置文件如下 cat /etc/nginx/nginx.conf user nginx; worker_processes ; #error_log logs/ ...

  2. centos 7.4 安装gitlab

    centos 7.4 安装gitlab #curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/scrip ...

  3. SpringBoot系列: Json的序列化和反序列化

    ============================= 控制 json 序列化/反序列化=============================1. @JsonIgnoreProperties的 ...

  4. Java入门系列 Lambda表达式

    https://blog.csdn.net/bitcarmanlee/article/details/70195403

  5. 微信接口 output {"errMsg":"translateVoice:fail, the permission value is offline verifying"}

    jsApiList : [ 'checkJsApi', 'startRecord', 'stopRecord','translateVoice','scanQRCode', 'openCard' ]增 ...

  6. 钉钉C# 使用数据接口要注意的问题

    1.钉钉的数据json全部使用的首字母小写的驼峰写法,如果首字母大写,将读取接口失败. 2.钉钉的文档同一个接口可能有simple和非simple两种写法,如果发现数据不全,可以把simple去掉试试 ...

  7. ASP.NET MVC 5 笔记

    1.   MVC 的常用特性 1)   System.Web.Mvc.ActionNameAttribute Ø  该特性用于将当前 Action 名称,改为一个指定的 Action 名称,路由匹配时 ...

  8. 向JSP中静态导入HTML文件时,运行jsp时,html中中文产生乱码问题最简单的解决方法

    在保证其他的编码格式一致的情况下 在html标签内,head标签外添加一下代码时可以完美解决 亲测 <%@page pageEncoding="UTF-8"%>

  9. 面向对象 ( OO ) 的程序设计——创建对象

    本文地址:http://www.cnblogs.com/veinyin/p/7608000.html  为了避免大量重复代码产生,可采用以下方法创建对象 1 工厂模式 function createP ...

  10. Java SE之正则表达式一:概述

    正则表达式 概念 定义:符合一定规则的表达式 作用:用于专门操作字符串 特点:用于一些特定的符号表示代码的操作,这样就简化了长篇的程序代码 好处:可以简化对字符串的复杂操作 弊端:符号定义越多,正则越 ...