Scala之继承

简介:

1. 继承

Scala语言通过 extends 关键字来继承类.
那么继承一个类有什么好处呢? 子类除了拥有继承自超类的方法和字段(即为val(常量), var(变量)所定义的), 还可以添加自己需要的新方法和新字段, 而且不但可以重写(override)超类的方法, 还可以重写超类的字段.

final 关键字

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

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

class Person {  final val key = 0
  val e = 1}class Kid extends Person {  // 报错: Value 'key' can not override final member
  // override val key = 1  
  override val e = 2 }object test extends App {  val k = new Kid;  println(k.key)  println(k.e)
}/*output02*/

2. 重写方法

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

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

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

  1. 当你拼错了要重写的方法名和字段名

  2. 当你不小心在新方法中使用了错误的参数类型

  3. 当你在超类中引入了新方法, 而这个新方法和子类的方法抵触

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

class Person {  final val key = 0
  val name = "person"
  val age = 1

  override def toString: String = getClass.getName + "[name=" + name + "]"}class Kid extends Person {  //override val key = 1
  override val name = "kid"
  override val age = 2

  override def toString: String = super.toString + "[age=" + age + "]"}object test extends App {  val k = new Kid;  println(k.key)  println(k.age)  println(k)
}/*output02chap08.Kid[name=kid][age=2]*/

3. 类型检查和转换

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

  if (kid.isInstanceOf[Kid]) {    val s = kid.asInstanceOf[Kid]
  }

如果kid是null, 则 kid.isInstanceOf[Kid] 返回false, kid.asInstanceOf[Kid] 返回null, 如果kid不是一个Kid, kid.asInstanceOf[Kid]将抛出异常

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

if (kid.getClass == classOf[Kid]) {    val s = kid.asInstanceOf[Kid]
  }

4. 超类构造

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

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

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

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

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

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

5. 重写字段

Scala的字段(Fields)由一个私有字段和取值器/改值器方法构成

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

class Smiler(val happy: String) {  override def toString: String = getClass.getName + "[happy: " + happy + "]"}class Laughter(veryhappy: String) extends Smiler(veryhappy) {  override val happy: String = "Laughter"
  override val toString: String = super.toString}

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

abstract class Smiler(val happy: String) {  def degree: Int}class Laughter(lhappy: String, override val degree: Int) extends Smiler(lhappy) {
}

注意如下限制:

  • def 只能重写另一个def

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

  • var 只能重写另一个抽象的var

6. 匿名子类

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

val alien = new Person("good") {    def greeting = "hi, good"
    }

7. 抽象类 与 抽象字段

  • 不需要对抽象方法和抽象字段用abstract关键字

  • 子类中重写超类的抽象方法和抽象字段时, 不需要override关键字

  • 只要类中存在抽象方法, 该类必须声明为 abstract

7.1 抽象类

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

abstract class Smiler(val happy: String) {  def degree: Int}
  • 在Scala中, 不需要对抽象方法用abstract关键字, 只是省去其方法体

  • 只要类中存在抽象方法, 该类必须声明为 abstract

  • 子类重写超类的抽象方法时, 不需要override关键字

class Laughter(lhappy: String) extends Smiler(lhappy) {  def degree = lhappy.hashCode }

7.2 抽象字段

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

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

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

val laught = new Abstract {  val id = 10
  var name = "laught"
  }

8. Scala继承层级

1182370-20170714100633478-364786788.png

  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的输出结果都是()

def printAny(x: Any) {print(x)}def printUnit(x: Unit) {print(x)}printAny("happy")printUnit("happy")/*output:happy()/*

9. 对象相等性

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





      本文转自zsdnr  51CTO博客,原文链接:http://blog.51cto.com/12942149/1949812,如需转载请自行联系原作者





相关文章
|
6月前
|
Java Scala
165 Scala 继承
165 Scala 继承
18 0
|
Java Scala
Scala快速入门-7-继承
继承类 extends 重写方法时必须用override 只有主构造器可以调用超类的主构造器 重写字段 抽象类、字段
|
分布式计算 Java Scala
scala面向对象编程之继承
scala使用extends关键字来实现继承。可以在子类中定义父类中没有的字段和方法,或者重写父类的方法。 示例1:实现简单继承
128 0
scala面向对象编程之继承
|
Scala 开发者
Scala 的继承注意事项|学习笔记
快速学习 Scala 的继承注意事项。
74 0
Scala 的继承注意事项|学习笔记
|
Java Scala 开发者
Scala 的继承快速入门|学习笔记
快速学习 Scala 的继承快速入门。
71 0
Scala 的继承快速入门|学习笔记
|
Java Scala Python
Java,Python,Scala比较(二)类与继承
UML图如下: 完整的Java代码如下: SimpleGeometricObject.java public class SimpleGeometricObject { private String col...
897 0
|
Java Scala
Scala入门到精通——第九节 继承与组合
主要内容 类的继承 构造函数执行顺序 方法重写 匿名类 多态与动态绑定 组合与继承的使用 1 类的继承 下类的代码演示了scala类的继承 //Person类 class Person(name:String,age:Int){ } //Student继承Person类 class Student(name:String,age:Int,var studen
3241 0
|
Scala C# Java
SCALA中类的继承
慢慢的,回想起以前学习JAVA和C#当中的的类的特性了。 感觉大同小异吧。。。 package com.hengheng.scala class OOPInScala { } class Student(name: String, age : Int, val major : ...
708 0
|
Java Scala
scala简要: 继承
版权声明:本文为半吊子子全栈工匠(wireless_com,同公众号)原创文章,未经允许不得转载。
684 0