zoukankan      html  css  js  c++  java
  • Scala for the Impatients---(8)Inheritance

    In this chapter, we only discuss the case in which a class inherits from another class. See Chapter 10 for inheriting traits —the Scala concept that generalizes Java interfaces.

    Extending a Class

    You extend a class in Scala just like you would in Java—with the extends keyword:

    class Employee extends Person {
    var salary: 0.0
    ...
    }

    As in Java, you specify fields and methods that are new to the subclass or that override methods in the superclass.

    As in Java, you can declare a class final so that it cannot be extended. You can also declare individual methods or fields final so that they cannot be overridden. Note that this is different from Java, where a final field is immutable, similar to val in Scala.

    Overriding Methods

    When overriding a non-abstract method, we should use the override modifier.

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

    Invoking a superclass method in Scala works exactly like in Java, with the keyword super :

    class Employee extends Person {
    ...
    override def toString = super.toString + "[salary=" + salary + "]"
    }

    Type Checks and Casts

    To test whether an object belongs to a given class, use the isInstanceOf method. If the test succeeds, you can use the asInstanceOf method to convert a reference to a subclass reference:

    if (p.isInstanceOf[Employee]) {
    val s = p.asInstanceOf[Employee] // s has type Employee
    ...
    }

    The p.isInstanceOf[Employee] test succeeds if p refers to an object of class Employee or its subclass (such as Manager ).

    If you want to test whether p refers to an Employee object, but not a subclass, use

    if (p.getClass == classOf[Employee])

    The classOf method is defined in the scala.Predef object that is always imported.

    Protected Fields and Methods

    Superclass Construction

    The auxiliary constructors of the subclass eventually call the primary constructor of the subclass. Only the primary constructor can call a superclass constructor. Recall that the primary constructor is intertwined with the class definition. The call to the superclass constructor is similarly intertwined. Here is an example:

    class Employee(name: String, age: Int, val salary : Double) extends Person(name, age)

    In Java, the equivalent code is quite a bit more verbose:

    public class Employee extends Person { // Java
    private double salary;
    public Employee(String name, int age, double salary) {
    super(name, age);
    this.salary = salary;
    }
    }

    In a Scala constructor, you can never call super(params) , as you would in Java, to call the superclass constructor.

    A Scala class can extend a Java class. Its primary constructor must invoke one of the constructors of the Java superclass. For example:

    class Square(x: Int, y: Int,  Int) extends
    java.awt.Rectangle(x, y, width, width)

      Overriding Fields

    You can override a val (or a parameterless def ) with another val field of the same name. The subclass has a private field and a public getter, and the getter overrides the superclass getter (or method).

    class Person(val name: String) {
        override def toString = getClass.getName + "[name=" + name + "]"
    }
    class SecretAgent(codename: String) extends Person(codename) {
        override val name = "secret" // Don't want to reveal name . . .
        override val toString = "secret" // . . . or class name
    }

    A more common case is to override an abstract def with a val , like

    abstract class Person { // See Section 8.8 for abstract classes
    def id: Int // Each person has an ID that is computed in some way
    ...
    }
    class Student( override val id: Int) extends Person
    // A student ID is simply provided in the constructor

    Anonymous Subclasses

    you make an instance of an anonymous subclass if you include a block with definitions or overrides, such as

    val alien = new Person("Fred") {
    def greeting = "Greetings, Earthling! My name is Fred."
    }

    Technically, this creates an object of a structural type —see Chapter 18 for details. The type is denoted as

    Person(def greeting: String)

    You can use this type as a parameter type(就是说这个type可以做函数参数):

    def meet(p: Person{def greeting: String}) {
        println(p.name + " says: " + p.greeting)
    }

    Abstract Classes

    you can use the abstract keyword to denote a class that cannot be instantiated, usually because one or more of its methods are not defined. For example

    abstract class Person(val name: String) {
    def id: Int // No method body—this is an abstract method
    }

    In Scala, unlike Java, you do not use the abstract keyword for an abstract method. A class with at least one abstract method must be declared abstract.

    In a subclass, you need not use the override keyword when you define a method that was abstract in the superclass.

    class Employee(name: String) extends Person(name) {
    def id = name.hashCode // override keyword not required
    }

    Abstract Fields

    An abstract field is simply a field without an initial value. For example 

    abstract class Person {
    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
    }
    

    Concrete subclasses must provide concrete fields, for example:

    class Employee(val id: Int) extends Person { // Subclass has concrete id property
    var name = "" // and concrete name property
    }

    As with methods, no override keyword is required in the subclass when you define a field that was abstract in the superclass.

    You can always customize an abstract field by using an anonymous type:

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

    Construction Order and Early Definitions

    When you override a val in a subclass and use the value in a superclass constructor, the resulting behavior is unintuitive.

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

    So what is the problem? Let's consider the process:

    1. The Ant constructor calls the Creature constructor before doing its own construction.
    2. The Creature constructor sets its range field to 10 .
    3. The Creature constructor, in order to initialize the env array, calls the range() getter.
    4. That method is overridden to yield the (as yet uninitialized) range field of the Ant class.
    5. The range method returns 0. (That is the initial value of all integer fields when an object is allocated.)
    6. env is set to an array of length 0 .
    7. The Ant constructor continues, setting its range field to 2 .

    Even though it appears as if range is either 10 or 2 , env has been set to an array of length 0. The moral is that you should not rely on the value of a val in the body of a constructor.

    There are several remedies.
      • Declare the val as final . This is safe but not very flexible.
      • Declare the val as lazy in the superclass (see Chapter 2). This is safe but a bit inefficient.
      • Use the early definition syntax in the subclass—see below.

    The “early definition” syntax lets you initialize val fields of a subclass before the superclass is executed. You place the val fields in a block after the extends keyword, like this:

    class Bug extends {
        override val range = 2
    } with Creature

    Note the with keyword before the superclass name. This keyword is normally used with traits—see Chapter 10.

    The Scala Inheritance Hierarchy

  • 相关阅读:
    OpenLayer 3 鹰眼控件和全屏显示
    OpenLayer 3 鼠标位置坐标显示控件
    Openlayer 3 图层列表控件(自定义)
    OpenLayers 3 的地图基本操作
    小米范工具系列之十四:小米范网站批量爬虫工具
    ruby所有版本下载地址
    常用代码块:使用时间生成数据库文件名
    收集些常用的正则--以后慢慢添加
    小米范工具系列最新下载地址
    小米范工具系列之十三:小米范验证码登录爆破工具
  • 原文地址:https://www.cnblogs.com/chaseblack/p/5876738.html
Copyright © 2011-2022 走看看