第10章 继承
10.1 继承类
和 Java 一样使用 extends 关键字,在定义中给出子类需要而超类没有的
字段和方法,或者重写超类的方法。
class Person { var name = "" }
class Employee extends Person { var salary = 0.0 def description = "An employee with name " + name + " and salary " + salary }
提示:
如果类声明为 final,他讲不能被继承。如果单个方法声明为 final,将不
能被重写。
10.2 重写方法
重写一个非抽象方法需要用 override 修饰符。
调用超类的方法使用 super 关键字
class Person { var name = "" override def toString = getClass.getName + "[name=" + name + "]" }
class Employee extends Person { var salary = 0.0 override def toString = super.toString + "[salary=" + salary + "]" }
10.3 类型检查和转换
要测试某个对象是否属于某个给定的类,可以用 isInstanceOf 方法。用
asInstanceOf 方法将引用转换为子类的引用。classof 获取对象的类名。
1)classOf[String] 就如同 Java 得 String.class
2)obj.isInstanceOf[T] 就如同 Java 的 Obj isInstanceof T
3)obj.asInstanceOf[T] 就如同 Java 的 (T)Obj
println("Hello".isInstanceOf[String]) println("Hello".asInstanceOf[String]) println(classOf[String])
10.4 受保护的字段和方法
protected 在 Scala 中比 Java 要更严格一点,即,只有继承关系才可以访问,同一个包下时不可以的。
10.5 超类的构造
类有一个主构造器和任意数量的辅助构造器,而每个辅助构造器都必须以对先前定义的辅助构造器
或主构造器的调用开始。子类的辅助构造器最终都会调用著构造器,只有主构造器可以调用超类的
构造器。辅助构造器永远都不可能直接调用超类的构造器。在Scala的构造器中,你不能调用 super(params).
** 当前类的【辅助构造器】,最终都会调用当前类的【主构造器】
** 子类的主构造器,最终都会调用父类的构造器(可以是辅助构造器,可以是主构造器)
class Dog(age: Int){
def this(){
this(10)
}
} val dog = new Dog(20) val dog = new Dog()
class Person(val name: String, val age: Int) { override def toString = getClass.getName + "[name=" + name + ",age=" + age + "]" }
class Employee(name: String, age: Int, val salary : Double) extends Person(name, age) { override def toString = super.toString + "[salary=" + salary + "]" }
10.6 重写字段(覆写字段)
子类改写父类或者抽象父类的字段,通过以下方式:
class Person1(val name: String, var age: Int) { println("主构造器已经被调用") val school = "五道口职业技术学院" def sleep = "8 hours" override def toString: String = "我的学校是:" + school + ",我的名字:" + name + ",我的年龄:" + age }
class Person2(name: String, age: Int) extends Person1(name, age){
override val school: String = "清华大学"
}
调用:
//覆写字段 val person = new Person2("nick", 20) println(person) //主构造器已经被调用 //我的学校是:清华大学,我的名字:nick,我的年龄:20
尖叫提示:
1、def 只能重写另一个 def
2、val 只能重写另一个 val 或不带参数的 def 不能重写 var
3、var 只能重写一个抽象的 var
val a = "123" //不能被 def 重写 def a = "123" //不带参数的 def 可以被 val 重写
什么是抽象 var?
sbstract class Person3{
var name: String //这就是一个抽象的var
}
10.7 匿名子类
和 Java 一样,你可以通过包含带有定义或重写的代码块的方式创建一个
匿名的子类:
class Person(val name: String) { override def toString = getClass.getName + "[name=" + name + "]" }
使用: val alien = new Person("Fred") { def greeting = "Greetings, Earthling! My name is Fred." }
println(alien.greeting)
10.8 抽象类
可以通过 abstract 关键字标记不能被实例化的类。方法不用标记
abstract,只要省掉方法体即可。抽象类可以拥有抽象字段,抽象字段就是没有初
始值的字段。
abstract class Person(val pname: String) { val id: Int // No initializer—this is an abstract field with an abstract getter method var name: String // Another abstract field, with abstract getter and setter methods def idString: Int // No method body—this is an abstract method }
class Employee(pname: String) extends Person(pname) { val id = 5; var name = ">>>" def idString = pname.hashCode // override keyword not required }