Scala 继承

来源:互联网 发布:ntfs for mac激活不了 编辑:程序博客网 时间:2024/06/05 19:55

摘自《快学Scala》

0.重点

  • extends,final关键字和Java中相同
  • 重写方法时必须用override
  • 只有主构造器可以调用超类的主构造器
  • 可以重写字段
  • 本章只探讨类继承自另一个类的情况

1.扩展类

class Employee extends Person{    var salary = 0.0}

和Java一样,将类声明为final,就不能被扩展了。

2.重写方法

Scala中重写一个非抽象方法必须使用override修饰符。

public class Person{    ...    override def toString = getClass.getName + "[name=" + name + "]"}

override修饰符可以给出有用的错误提示
* 当你拼错了要重写的方法名
* 当你不小心在新方法中使用了错误的参数类型
* 当你在超类中引入了新的方法,而这个新方法与子类的方法相抵触】

Scala中调用超类的方法:super关键字。

public class Employee extends Person{    ...    override def toString = super.toString + "[salary=" + salary + "]"}super.toString会调用超类的toString方法——即Person.toString

类型检查和转换

要测试某个对象是否属于某个给定的类,可以用isInstanceOf方法。如果测试成功,就可以用asInstanceOf方法将引用转换为子类的引用:

if (p.isInstanceOf[Employee]){    val s = p.asInstanceOf[Employee] //s的类型为Employee}// 如果你想要测试p指向的是一个Employee对象但又不是其子类,可以用:if(p.getClass == classOf[Employee])

与类型检查和转换相比,模式匹配是更好的选择:

p match{    case s:Employee => ...    case _ => //p不是Employee}

4.受保护字段和方法

同Java和C++一样,可以将字段或方法声明为protected,这样的成员可以被任何子类访问,但不能从其他位置看到。
与Java不同,protected的成员对于类所属的包而言,是不可见的。
Scala还提供了一个protected[this]的变体,将访问权限限定在当前对象。类似private[this].

5.超类的构造

6.重写字段

class Person(val name:String){    override def toString = getClass.getName + "[name= + name + "]"}class SecretAgent(codename:String) extends Person(codename){    override val name = "secret"     override val toString = "secret"}

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

abstract class Person{    def id:Int     ...}class Student(override val id:Int) extends Person //学生id通过构造器输入

7.匿名子类

val alien = new Person("Fred"){    def greeting = "Greetings, Earthling! My name is Fred."}def meet(p:Person{def greeting:String}){    println(p.name + "says:" + p.greeting)}

8.抽象类

和Java一样,可以用abstract关键字来标记不能被实例化的类,通常这是因为它的一个或几个方法没有被完整定义。例如:

abstract class Person(val name:String){    def id:Int //没有方法体,这是个抽象方法}

如果某个类至少存在一个抽象方法,则该类必须声明为abstract。
在子类中写超类的抽象方法时,不需要使用override关键字。

class Employee(name:String) extends Person(name){    def id = name.hashCode // 不需要override关键字}

9.抽象字段

抽象字端就是一个没有初始值的字段。如:

abstract class Person{    val id:Int //没有初始化——这是一个带有抽象的getter方法的抽象字段    var name:String //另一个抽象字段,带有抽象的getter和setter方法}

具体的子类必须提供具体的字段:

class Employee(val id:Int) extends Person{ //子类有具体的id属性    var name=""//和具体的name属性}

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

val fred = new Person{    val id = 1729    var name = "Fred"}

10.构造顺序和提前定义

class Creature{    val range:Int = 10    val env:Array[Int] = new Array[Int](range)}class Ant extends{    override val range = 2}with Creature

提前定义的等号右侧只能引用之前已有的提前定义,而不能使用类中的其他字段或方法。

0 0
原创粉丝点击