14 Scala abstract classes and features of scala series

17 abstract class and trait

Abstract class:

Abstract classes are similar to Java, except that there is no attribute abstraction in Java, and scala can have attribute abstraction;

Characteristics:

The trait can be understood as an upgraded interface in Java

In Java, interfaces cannot declare properties without values and methods with implementations, while Scala can declare properties without values and methods with implementations;

rewrite:

Rewriting is similar to Java, except that there is no concept of rewriting attributes in Java, while scala can rewrite attributes;

Differences in the use of idiosyncratic and abstract classes:

Only one abstract class can be inherited, but multiple traits can be implemented. This is the same as Java;

The details are described below

17.1 abstract classes

1) When overriding the non abstract members (including fields and methods) of the parent class, the override keyword must be added;

package day03
abstract class Car {
  // Define common attributes
  val name:String = "vehicle"
  // Define abstract attributes (attributes are not assigned)
  val brand:String
  // Define common methods
  def description = {
    println("This is a common method in an abstract class")
  }
  // Define abstract method (method has no method body)
  def action():Unit
}
// Defines that a subclass inherits from a parent class
class BYDCar extends Car{
  // The subclass overrides the abstract member of the parent class, with or without override
  val brand: String = "BYD"
  def action(): Unit = {
    println("The developed blade battery is safer to use")
  }
  // If a subclass overrides a non Abstract member of the parent class, override must be added
  override val name: String = "tram"
  override def description: Unit = {
    super.description
    println(s"${brand} ${name}")
    action()
  }
}
object CarDemo{
  def main(args: Array[String]): Unit = {
    val car = new BYDCar
    car.description
  }
}

2) If the parent class has a constructor, the main constructor of the child class must call the main constructor or auxiliary constructor of the parent class.

The auxiliary constructor of a subclass cannot call the constructor of a parent class.

package day03
abstract class Car(val color:String) {
  var price:Double = _
  def this(color:String, price:Double) = {
    this(color)
    this.price = price
  }
  // Define common attributes
  val name:String = "vehicle"
  // Define abstract attributes (attributes are not assigned)
  val brand:String
  // Define common methods
  def description = {
    println("This is a common method in an abstract class")
  }
  // Define abstract method (method has no method body)
  def action():Unit
}
// Defines that a subclass inherits from a parent class
// The subclass main constructor inherits the parent class's main constructor
class BYDCar(color:String, types:String) extends Car(color:String){
  // The subclass overrides the abstract member of the parent class, with or without override
  val brand: String = "BYD"
  def action(): Unit = {
    println("The developed blade battery is safer to use")
  }
  // If a subclass overrides a non Abstract member of the parent class, override must be added
  override val name: String = "tram"
  override def description: Unit = {
    super.description
    println(s"${brand} ${color} ${types} ${name}")
    action()
  }
}
// An auxiliary constructor that inherits the parent class
class WULINGCar(color:String,price:Double, types:String) extends Car(color:String, price:Double){
  // Subclasses override the abstract members of the parent class, with or without override
  val brand: String = "Wuling"
  def action(): Unit = {
    println("Popular choice, sales lever drop")
  }
  // If a subclass overrides a non Abstract member of the parent class, override must be added
  override val name: String = "tram"
  override def description: Unit = {
    super.description
    println(s"${brand} ${color} ${types} ${name}")
    println(s"People friendly price: ${price}")
    action()
  }
}
object CarDemo{
  def main(args: Array[String]): Unit = {
    val car = new BYDCar("Brilliant blue", "Qin Dynasty DMI Oil electric mixing")
    car.description
    println("-----------------")
    val car2 = new WULINGCar("Various colors", 28800,"Agatsuma  Mini")
    car2.description
  }
}

17.2 characteristics

The trait keyword is required to define the trait;

Traits can contain abstract members and non abstract members, which is similar to scala's abstract class. When abstract members are included, the abstract keyword is not required;

In Scala, the extends keyword is used for both inherited classes and inherited traits;

When rewriting the method of attributes, there is no need to give the override keyword;

package day03
trait Fly {
  // Define common attributes
  val name:String = "fly"
  // Define abstract properties
  val maxFlyHigh:Int
  // Define common methods
  def description = {
    println("This is the common method in traits")
  }
  // Define abstract methods
  def action():Unit
}
class Bird extends Fly{
  // Override abstract member
  val maxFlyHigh: Int = 1000
  def action(): Unit = {
    println("Birds fly with their wings")
  }
  // Override non abstract members
  override val name: String = "Flamingo"
  override def description: Unit = {
    super.description
    println(s"${name}")
    action()
    println(s"Maximum flight altitude: ${maxFlyHigh}")
  }
}
object TraitTest{
  def main(args: Array[String]): Unit = {
    val bird = new Bird
    bird.description
  }
}

When you do not inherit a class and directly implement a trait, you can use extensions instead of with. When you implement multiple traits, you can use multiple with, but you must first extend the first one

For example, class T1 extends T2 with T3 with T4

package day03
trait Fly {
  // Define common attributes
  val name:String = "fly"
  // Define abstract properties
  val maxFlyHigh:Int
  // Define common methods
  def description = {
    println("This is the common method in traits")
  }
  // Define abstract methods
  def action():Unit
}
trait Run{
  def run():Unit
}
class Bird extends Fly{
  // Override abstract member
  val maxFlyHigh: Int = 1000
  def action(): Unit = {
    println("Birds fly with their wings")
  }
  // Override non abstract members
  override val name: String = "Flamingo"
  override def description: Unit = {
    super.description
    println(s"${name}")
    action()
    println(s"Maximum flight altitude: ${maxFlyHigh}")
  }
}
// Realize multiple characteristics with
class AirPlane extends Fly with Run{
  override val maxFlyHigh: Int = 10000
  override def action(): Unit = {
    println("Planes fly with wings")
  }
  override def run(): Unit = {
    println("The plane runs on wheels")
  }
  override def description: Unit = {
    super.description
    action()
    run()
    println(s"Maximum flight altitude: ${maxFlyHigh}")
  }
}
object TraitTest{
  def main(args: Array[String]): Unit = {
    val bird = new Bird
    bird.description
    println("------------------")
    val plane = new AirPlane
    plane.description
  }
}

Characteristics realize the logic of construction through the initialization of fields and the composition of statements in other characteristics.

But you cannot new instances.

trait T1{
  // Trait construction execution
  val a:String = "aaa"
  println(a)
  def t1():Unit
}
trait T2{
  // Trait construction execution
  val b:String = "bbb"
  println(b)
  def t2():Unit
}
class T1Sub extends T1 with T2{
  //This type of construction execution
  val c:String = "ccc"
  println(c)
      
  def t1():Unit={
    println("do t1()")
  }
  def t2():Unit={
    println("do t2()")
  }
}
object T1SubTest{
  def main(args: Array[String]): Unit = {
    // When calling new T1Sub, execute the construction of T1 first, then T2, and then this kind of construction 
    val t = new T1Sub
    t.t1()
    t.t2()
  }
}
//-----------Operation results-----------------
aaa
bbb
ccc
do t1()
do t2()

When to use idiosyncratic and abstract classes?
Use angle
Abstract classes are used for primary and secondary relations, and traits are used for additional functions, such as spider man.
Grammatical Perspective
1) Give priority to traits. It is convenient for a class to extend multiple characteristics, but it can only extend one abstract class.
2) If you need constructor parameters, use abstract classes. Because abstract classes can define constructors with parameters, but not attributes.

Original article of Haiyu tribe, original link: http://hainiubl.com/topics/75749

Keywords: Scala

Added by smilepak on Fri, 21 Jan 2022 02:39:05 +0200