- 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")
}
}
来源:CSDN
作者:尘无和尚
链接:https://blog.csdn.net/weixin_40450867/article/details/103481785