8 继承

十年热恋 提交于 2019-12-10 22:46:39

  • extends、final关键字与java相同
  • 重写方法必须用override
  • 只有主构造器可以调用超类的主构造器
  • 可以重写字段
  • 本章只介绍继承类,继承特质的后面再探讨

扩展类

  • 扩展类同Java一样,(又是跟Java一样,都不会Java),使用extends关键字
  • 在定义中可以给出子类需要但是超类没有的字段和方法,或者重写超类的方法
  • 一个类被声明为final,就不能被继承,字段或方法也是如此,声明为final就不能被重写了。在Java中不一样,final字段是不可变的,类似于scala 中的val
class Person{
  val name = "Bob"
  val age = 1
  final var id = 1
  def description() = println(s"${name} ,id:${id} is ${age} years old")
}

class Employee extends Person{
  var salary = 0.0
  override val name = "Saha"
  override val age: Int = 3
  id = 9  
  override def description() = println(s"${name} ,id:${id} is ${age} years old")
}

object hello extends App{
  val p = new Person
  val e = new Employee
  p.description()
  e.description()
}

重写方法

  • 重写一个非抽象方法必须使用override修饰符,重写非抽象字段也是
  • override的作用
    – 检查拼错了的要重写的方法名
    – 检查新方法的参数类型
    – 超类的新的方法与子类的方法相抵触
  • 调用超类的方法和Java完全一样,使用super关键字
class Person{
  val name = "Bob"
  val age = 1
  final var id = 1
  override def toString() = s"${name} ,id:${id} is ${age} years old"
}

class Employee extends Person{
  var salary = 700
  override val name = "Saha"
  override val age: Int = 3
  id = 9
  override def toString() = s"${super.toString()} and salary is ${salary} "

}

object hello extends App{
  val p = new Person
  val e = new Employee
  println(p)
  println(e)
}

类型检查和转换

  • 判断某个对象是不是给定类,用isInstanceOf[类]方法,如果为true可以用asInstanceOf[类]方法将其转换为子类的引用
  • p.isInstanceOf[A类]方法判断的p对象是不是A类或者A类的子类,如果是则为true
  • 如果想判断是不是纯粹的A类,得用p.getClass == classOf[Employee]
  • 类型转换后只保留新类的字段,例如Employee新增的salary字段在转换为Person类的时候就没有了。
scala> p.isInstanceOf[Employee]
res1: Boolean = false

scala> p.isInstanceOf[Person]
res2: Boolean = true

scala> e.isInstanceOf[Employee]
res3: Boolean = true

scala> e.isInstanceOf[Person]
res4: Boolean = true
// 类型转换
scala> val pe = e.asInstanceOf[Person]
pe: Person = Saha ,id:9 is 3 years old and salary is 700
// 判断是不是那个类
scala> e.getClass == classOf[Person]
res10: Boolean = false

scala> e.getClass == classOf[Employee]
res11: Boolean = true

Scala和Java中的类型检查和转换

Scala Java
obj.isInstanceOf[C1] obj instanceof C1
obj.asInstanceOf[C1] C1 obj
classOf[C1] C1.getClass
  • 更好的方法是模式匹配,可以看到类型匹配的是跟isInstanceOf方法相同
  e match {
    //完全是Person类
    case _ if (e.getClass == classOf[Person] )=> println("person")
    //是Person类及其子类
    case person:Person => println("Person")
    //是Employee的类及其子类
    case employee:Employee => println("employee")
    //除了上述三种情况之外
    case _ => println("不知道什么类")
  }

受保护字段和方法

  • protected关键字,成员可以被任意子类访问,但不能从其他位置看到
  • protected成员对于类所属的包是不可见的,与Java不同,如果需要的话可以使用包修饰符
  • protected[this] 将权限限定在当前对象

超类的构造

  • 辅助构造器不能直接调用超类的主构造器
  • 子类的辅助构造器最终都会调用主构造器,只有主构造器可以调用超类的构造器
  • Scala类扩展Java类的时候,主构造器必须调用Java超类的一个构造方法
//主构造器
class Employee(name:String,id:Int,val saraly:Double) extends Person(name,age)
//扩展java
class PathWriter(p:Path,cs:Charset) extends java.io.PrintWriter(Files.newBufferedWriter(p,cs)) 

重写字段

  • def 只能重写 def
  • val只能重写另一个val或不带参数的def
  • var只能重写另一个抽象的var
  • 非抽象类的var,子类可以直接修改变量的内容,而不需要重写,如果父类是var,所有的子类只能被动接受
用val 用def 用var
重写val 子类有一个私有字段,getter方法重写超类的getter方法 不能 不能
重写def 子类有一个私有字段,getter方法重写超类的方法 同java var可以重写getter/setter对,只重写getter会报错
重写var 不能 不能 超类的var是抽象的时候才可以

匿名子类

  • 同Java一样,可以通过包含带有定义或重写的代码块的方式创建一个匿名的子类
  • 会创建一个结构类型的对象Person{def greeting: String; def hello: Int}
class Person(val name : String)

 val alien =  new  Person("Fred"){def greeting = "My name is Fred";def hello = 12}
// alien: Person{def greeting: String; def hello: Int} = $anon$1@3071d086

  • 可以使用上面的结构类型。(已经超过我的智力范围)
def meet(p:Person{def greeting: String; def hello: Int}){println(s"${p.name} says ${p.greeting} ${p.hello} times")}
// warning: there were two feature warnings; re-run with -feature for details
meet: (p: Person{def greeting: String; def hello: Int})Unit

抽象类

  • 用abstract来标记不能被实例化的类,抽象类不能被实例化,因为某个或某几个方法没有被完整定义
  • 不用对抽象方法或抽象字段使用abstract关键字,省去方法体或不给初始值即可
  • 如果至少存在一个抽象字段或方法,该类必须声明为abstract
  • 子类必须提供全部的抽象方法或抽象字段的实现
  • 对于val生成getter方法,对于var 生成getter和setter方法。生成的java类并不带字段
  • 子类中重写超类的抽象方法不需要用override关键字,当然用了也没问题
abstract class Person3(){
  val id : Int
  var age : Int
  val name:String
  def desc = println(s"Hello ${name} is ${age} years old")
}
class Managee extends Person3{
  val id = 3
  var age = 3
  val name = ""

  override def desc: Unit = {
    super.desc
    println("haha")
  }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!