scala--object-oriented-inheritance-★★★★

extends、override、super

extends

  • Inheritance in Scala and Java also use the extends keyword;
  • The subclass can inherit or override the field and method of the parent class, and can also implement the field and method specific to the subclass

verride

  • In Scala, if a subclass wants to override a field or method in the parent class, use the override keyword;

super

  • To call the overridden method in the parent class in the subclass, use the super keyword to indicate the parent class method to be called.
  • note
    • Final modified classes cannot be inherited
    • Final modified fields or methods cannot be overwritten
    • Private modified fields and methods cannot be inherited by subclasses
    • Use the override keyword to override the val field
    • Use the override keyword to re-assign the var field (note that it is not a redefinition)
    • The override keyword can help developers find errors in the code as early as possible, such as method name spelling errors, parameter errors, etc., so it is recommended to add the override keyword when overwriting;

Extension: protected description

  • Like Java, Scala can also use the protected keyword to modify fields and methods.
  • But it is more strict than Java: only the inheritance relationship can be accessed, and it is not possible under the same package
  • In the subclass, you can directly access the protected modified field and method of the parent class without using the super keyword;
  • You can also use the protected[this] keyword to only allow access to the field and method of the parent class in the current class, and not allow access to the field and method of the parent class through other subclass objects.
package cn.hanjiaxiaozhi.extendsdemo
​
/**
 * Author hanjiaxiaozhi
 * Date 2020/7/16 15:52
 * Desc 
 */
class Person {
    
    
  val name = "super"
  var age = 18def sayName = {
    
    
    println("Person--sayName")
  }def sayHello={
    
    
    println("hello")
  }
}
//Student继承了Person,将相当于有了Person中的非私有的一切
class Student extends Person{
    
    
  //如果子类要覆盖可以使用override
  override
  val name = "sub" //val修饰的可以覆盖的
​
  age = 20 //var修饰的可以重新赋值override
  def sayName = {
    
    
    //super.sayName //super表示调用父类的
    println("Student--sayName")
  }//sayHello如果不覆盖就直接继承过来了
  /*override
  def sayHello={
    println("hello")
  }*///子类也可以定义自己的变量
  val nickName = "xx"//子类也可以编写自己的方法
  def saybye(): Unit ={
    
    
    println("good bye~~" + nickName)
  }
}object Test{
    
    
  def main(args: Array[String]): Unit = {
    
    
    val s: Student = new Student()
    s.sayName
    s.sayHello
    s.saybye
    println("==================")
    val p: Person = new Student()//多态,父类类型接收子类对象,不需要强转
    p.sayName //本质是调用的是Student的
    p.sayHello//本质是调用的是Student的
    //p.saybye //如果使用的Person接收Student对象,那么不能调用Student中的方法
    //如果非得调用子类特有的方法得强转
    p.asInstanceOf[Student].saybye()
  }
}

Type judgment, acquisition, conversion

  • isInstanceOf 和 asInstanceOf
    • obj.isInstanceOf[XX类名]
      • Determine whether obj is an instance of type XX (determine whether the object is an instance of the specified class and its subclasses)
      • Similar to in Java: obj instanceof xx
    • obj.asInstanceOf[XX class name]
      • Convert obj into an instance of type XX (the new parent class cannot be forced to be a subclass)
      • Similar to Java: (XX)obj
  • getClass 和 classOf
    • obj.getClass
      • Can accurately obtain the type of object
      • It is in Java: object.getClass
    • classOf[XX class name]
      • Can accurately obtain the type of the class
      • Similar to Java: class name.class
  • note:
    • If the object is null,
      • isInstanceOf must return false,
      • asInstanceOf must return null;
  • Scala and Java type checking and conversion analogy
Scala Java
obj.isInstanceOf[XX类名] obj instanceof XX类名
obj.asInstanceOf[XX class name] (XX class name)obj
obj.getClass obj.getClass
classOf[XX class name] XX class name.class
  • Use pattern matching for type judgment
    • Use pattern matching for type judgment (pattern matching will be discussed later)
    • Functionally speaking, it is the same as isInstanceOf. It mainly determines whether it is an object of this class or its subclasses. It is not an accurate judgment.
    • Syntactically speaking, it is similar to the switch case in Java
    • In actual development, such as spark source code, a large number of pattern matching is used for type judgment, which is more concise, maintainable, and extensible
package cn.hanjiaxiaozhi.extendsdemo
​
/**
 * Author hanjiaxiaozhi
 * Date 2020/7/16 16:22
 * Desc 
 */
class Person2 {
    
    
}class Student2 extends Person2
​
object Test2 {
    
    
  def main(args: Array[String]): Unit = {
    
    
    val p: Person2 = new Student2 //父类类型接收子类对象
    val s: Student2 = null
    //1. 对象.isInstanceOf[类名]表示判断对象是否属于某个类型或其子类型,如果对象为空返回null
    println(p.isInstanceOf[Student2]) //true
    println(p.isInstanceOf[Person2]) //true
    println(s.isInstanceOf[Student2]) //false
    println("====================")//2. 对象.getClass获取对象真实类型/字节码类型 == classOf[类名]是获取类的字节码类型
    println(p.getClass == classOf[Student2]) //true
    println(p.getClass == classOf[Person2]) //flase
    println("====================")//3. 对象.asInstanceOf[类型]--类型转换
    if (p.isInstanceOf[Student2]){
    
    
      val s2: Student2 = p.asInstanceOf[Student2]
      println("p已经转为Student2类型")
    }
  }
}
  • to sum up
    • Comparison with java:
  • judgment
    • scala:object.isInstanceOf[class name]
    • java: object instanceof type
  • Obtain
    • scala: object.getClass or calssOf[class name]
    • java: object.getClass or class name.Class or Class.forName("package class path")
  • Conversion
    • scala: object.asInstanceOf[type]
    • java: (type) object

Constructor execution order

  • Each class in Scala can have a main constructor and any number of auxiliary constructors,
  • The first line of the auxiliary constructor must call other auxiliary constructors or the main constructor code;
  • It is impossible for the auxiliary constructor of the subclass to directly call the constructor of the parent class, and the constructor of the parent class can only be called in the main constructor of the subclass.
  • Fields that have been defined by the constructor of the parent class. When the subclass is in use, it does not need to be modified with val/var, otherwise it will be considered that the subclass should override the field of the parent class.
package cn.hanjiaxiaozhi.extendsdemo
​
/**
 * Author hanjiaxiaozhi
 * Date 2020/7/16 16:38
 * Desc 
 */
class Person3 (val name: String, val age: Int) {
    
    
  println("父类的主构造器")
  var score: Double = 0.0
  var address: String = "beijing"def this(name: String, score: Double) = {
    
    
    //每个辅助构造器的第一行都必须调用其他辅助构造器或者主构造器代码
    this(name, 30)
    println("父类的第一个辅助构造器")
    this.score = score
  }//其他辅助构造器
  def this(name: String, address: String) = {
    
    
    this(name, 100.0)
    println("父类的第二个辅助构造器")
    this.address = address
  }
}//子类的继承父类可以调用父类的任何一个构造器,只要保证最终调用的是父的主构造器即可
class Student3(name: String, score: Double) extends Person3(name, score){
    
    
  println("子类的主构造器")
}object Test3{
    
    
  def main(args: Array[String]): Unit = {
    
    
    val s = new Student3("jack",99.9)
    //父类的主构造器
    //父类的第一个辅助构造器
    //子类的主构造器
    println(s.name)
    println(s.age)
    println(s.score)
    println(s.address)
  }
}
  • to sum up
    • Scala, like Java, executes the construction of the parent first and then the construction of the child
    • There are also main and auxiliary constructors in Scala
    • The auxiliary constructor eventually has to call the main constructor

Abstract class

  • Abstract classes, abstract methods, and abstract fields
    • If a class contains an abstract method or abstract field, you must use abstract to declare the class as an abstract class, which cannot be instantiated
    • If in the parent class, there are some methods that cannot be implemented immediately, and need to be overridden by different subclasses, and rewrite to implement different methods. At this time, these methods in the parent class can be written to contain only method signatures, without The form of method body, this form is called abstract method
    • If a field is defined in the parent class, but no initial value is given, then this field is an abstract field
  • note
    • When the abstract method of the abstract class is overridden in the subclass, the override keyword can be omitted, but it is recommended to add; the override keyword must be used to override the non-abstract method of the parent class
    • There can be ordinary fields and methods in abstract classes

Extension: Anonymous inner class

  • Description
    • Anonymous inner classes are very common in Scala. The source code of Spark uses a lot of anonymous inner classes;
    • An anonymous inner class is to define a subclass without a name, create its object directly, and then assign a reference to the object to a variable
  • Usually the anonymous inner class object is passed to other methods or functions for use.
package cn.hanjiaxiaozhi.extendsdemo
​
/**
 * Author hanjiaxiaozhi
 * Date 2020/7/16 16:48
 * Desc 
 */
//abstract修饰的类称为抽象类
//里面可以有抽象方法或普通方法,也可以有抽象字段或普通字段
//有抽象字段/抽象方法的类一定是抽象类
//抽象类并不一定必须有抽象方法和抽象字段
abstract class Shape {
    
    
  //定义一个抽象字段,不用给值
  val name:String//定义一个抽象方法,不用给方法体,注意:得给返回类型,要不然就是Unit
  def getArea:Double}//定义一些图形继承抽象类Shape,实现getArea求面积的方法
class Square(val edge:Double) extends Shape {
    
    
  override val name: String = "正方形"override def getArea: Double = {
    
    
    edge * edge
  }
}
class Rectangle(val length:Double,val width:Double) extends Shape {
    
    
  override val name: String = "长方形"override def getArea: Double = {
    
    
    length * width
  }
}
class Cirle(val radius:Double) extends Shape {
    
    
  override val name: String = "圆形"override def getArea: Double = {
    
    
    math.Pi * radius * radius
  }
}
object Test4{
    
    
  def main(args: Array[String]): Unit = {
    
    
    val s1:Shape = new Square(2)
    val s2:Shape = new Rectangle(4,2)
    val s3:Shape = new Cirle(1)
    println(s1.name + " 面积为: " +s1.getArea)
    println(s2.name + " 面积为: " +s2.getArea)
    println(s3.name + " 面积为: " +s3.getArea)
    //正方形 面积为: 4.0
    //长方形 面积为: 8.0
    //圆形 面积为: 3.141592653589793
  }
}
​
​

Guess you like

Origin blog.csdn.net/qq_46893497/article/details/114041480