zoukankan      html  css  js  c++  java
  • 10.Scala-继承

    第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 }
    子类实现抽象方法可以省略(不建议) override。

    10.9 构造顺序和提前定义

    当子类重写了父类的方法或者字段后,父类又依赖这些字段或者方法初始化,这个时候就会出现问题,
    比如:
    class Creature {
      val range: Int = 10
      val env: Array[Int] = new Array[Int](range)
    }
    


    class Ant extends Creature {   override val range = 2 }
    构造顺序:
    1) Ant 的构造器在做它自己的构造之前,调用 Creature 的构造器
    2) Creature 的构造器将它的 range 字段设为 10
    3) Creature 的构造器为了初始化 env 数组,调用 range()取值器
    4) 该方法被重写以输出(还未初始化的)Ant 类的 range 字段值
    5) range 方法返回 0,(这是对象被分配空间时所有整形字段的初始值)
    6) env 被设为长度为 0 的数组。
    7) Ant 构造器继续执行,将其 range 字段设为 2.
    那么 env 的大小是多少?是 0,
     
    解决这个问题,可以有 3 种方法:
    1) 将 val 声明为 final,这样子类不可改写。
    2) 将超类中将 val 声明为 lazy,这样安全但并不高效
    3) 可以使用提前定义语法,可以在超类的构造器执行之前初始化子类的 val 字段,
    class Ant2 extends {
      override val range = 3
    } with Creature

    笔记:

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



    调用:
    val ant = new Ant
    println(ant.range) //20
    println(ant.env.length) //0
    
    
    val ant2 = new Ant2
    println(ant2.range) //20
    println(ant2.env.length) //20
    
    
    
     

    10.10 Scala 继承层级

    在scala中,所有其他类都是AnyRef的子类,类似Java的Object。
    AnyVal和AnyRef都扩展自Any类。Any类是跟节点
    Any中定义了isInstanceOf、asInstanceOf方法,以及哈希方法等。
    Null类型的唯一实例就是null对象。可以将null赋值给任何引用(AnyRef),但不能赋值给值类型(AnyVal)的变量。
    Nothing类型没有实例。它对于泛型结构是有用处的,举例:空列表Nil的类型是List[Nothing],它是List[T]的子类型,T可以是任何类。

    ::Nil 这是产生一个新的集合,不是在原有基础上追加

     

  • 相关阅读:
    JavaEE——SpringMVC(11)--拦截器
    JavaEE——SpringMVC(10)--文件上传 CommonsMultipartResovler
    codeforces 460A Vasya and Socks 解题报告
    hdu 1541 Stars 解题报告
    hdu 1166 敌兵布阵 解题报告
    poj 2771 Guardian of Decency 解题报告
    hdu 1514 Free Candies 解题报告
    poj 3020 Antenna Placement 解题报告
    BestCoder5 1001 Poor Hanamichi(hdu 4956) 解题报告
    poj 1325 Machine Schedule 解题报告
  • 原文地址:https://www.cnblogs.com/LXL616/p/11128960.html
Copyright © 2011-2022 走看看