Object-oriented Scala (2)

Table of contents

Singleton object (companion object):

There are two common ways to create objects:

(1) Use the constructor to construct (new)

(2) Use static methods

 Definition of companion object:

apply method:

The call of the apply method:

Singleton mode:

There are two types of singleton patterns:

1. Lazy style

2. Hungry Chinese style: (recommended)

Traits:

Basic syntax:

illustrate

Trait Overlay:

The difference between traits and abstract classes:

Singleton object (companion object):

The Scala language is a fully object-oriented language, so there are no static operations (that is, there is no static concept in Scala). But in order to be able to interact with the Java language (because there is a static concept in Java), a special object is created to simulate a class object, which is a singleton object. If the name of the singleton object is consistent with the name of the class, it is called the companion object of the class of the singleton object, and all "static" content of this class can be placed and declared in its companion object.

There are two common ways to create objects:

(1) Use the constructor to construct (new)

    val person0 = new Person09()

(2) Use static methods

(In Scala there is no static method equivalent to object---companion object)

    val person01: Person09 = Person09.getPerson()

 Definition of companion object:

object Person09{
  def getPerson():Person09=new Person09
}

          Method 2 is mainly because it cannot be new when the constructor is privatized. In this case, it is necessary to use the companion object construction           

class Person09 private{
  val name :String="张三"
}

apply method:

In Scala, an apply() method template is introduced to replace the above-mentioned construction method of the companion object. The method is created in the companion object, and the apply method can be called directly in the main method.

The apply() method has been improved in Scala. When the function is called, the method name can not be written, and the method can be called directly.

The call of the apply method:

    val person0: Person09 = Person09()

The apply method can also be customized arbitrarily, it is not necessary to create an object like a template

The feature is that you can not write the method name

The apply method can be called directly by Person09()

The system is widely used in collections, calling the apply method of the object

The following collection Array is an object. Using .var to automatically generate objects is actually an Array collection

    val ints: Array[Int] = Array(1, 2, 3, 4)  

Singleton mode:

The singleton mode is to ensure that a class has only one instance, that is, the object cannot be created casually, so the construction method must be private for privatization and cannot be instantiated by the outside world. This instance is the class member variable of the current class, that is, the class static member variable. This static variable needs to be provided to the outside world, so it is necessary to provide a static method to provide the current instance to the outside world

There are two types of singleton patterns:

1. Lazy style

Occupies less memory (reduces the number of created objects), and is not thread-safe (all enter the if judgment in a certain period of time, all of which are true, and will be assigned to generate variables, which will result in thread safety --- only when it is initialized for the first time)

  class Singleton09 private{
  }
  object Singleton09{        //相当于静态方法 在静态方法中创建对象 便于外边的访问
    //先声明属性     先声明为null  后边获取的时候再赋值
    private var singleton:Singleton09=null;
    def apply(): Singleton09 = {
              if (singleton==null)
                {
                  singleton = new Singleton09
                }
                  singleton
    }
  }

2. Hungry Chinese style: (recommended)

Hungry Chinese style has no thread safety problem, it is easy to write, and takes up a lot of memory (created in advance). It first creates the object in the companion object and loads the class in the jvm, thus avoiding the thread safety problem

object Singleton09 {
  private var singleton: Singleton09 = new Singleton09;
  def apply(): Singleton09 = singleton
}

Judge the singleton mode:

  def main(args: Array[String]): Unit = {
    //判断单例模式是否正确
    val singleton:Singleton09=Singleton09();
    val singleton1:Singleton09=Singleton09();
    println(singleton)
    println(singleton1)
  }

 You can see that the address values ​​are the same

Traits:

In the Scala language, traits (features) are used to replace the concept of interfaces , that is, multiple classes have the same
When the trait (feature) of the trait (feature) can be isolated, the trait (feature) can be declared using the keyword trait .
A trait in Scala can have either abstract properties and methods or concrete properties and methods . A class can
to mixin ( mixin ) multiple traits . This feeling is similar to the abstract class in Java ( now it is an interface ---> the current interface can have specific properties and methods ).
A class has a certain trait (feature), which means that the class satisfies all the elements of the trait (feature),
Therefore, when using, the extends keyword is also used . If there are multiple traits or parent classes, then you need to use with
Keyword link.

Basic syntax:

No parent class : class class-name extends trait 1 with trait 2 with trait 3 ...
Has a parent class : class class name extends parent class with trait 1 with trait 2 with trait 3...

illustrate

( 1 ) Relationship between classes and traits: use inheritance.
( 2 ) When a class inherits traits, the first conjunction is extends , followed by with .
( 3 ) If a class inherits traits and parent classes at the same time, the parent class should be written after extends
(4) A class can be mixed with multiple traits
(5) All Java interfaces can be used as Scala traits
  class Person11 extends Young11 with old11 with java.io.Serializable{}

(6) Dynamic mix-in: the functions of classes can be flexibly extended

        (6.1) Dynamic mix-in: mix-in a trait when creating an object without making the class mix-in the trait
        (6.2) If there is an unimplemented method in the mixed-in trait, it needs to be implemented
        (6.3) If there are abstract methods and properties in the trait, they also need to be rewritten
(7) Trait conflict: If the inherited parent class and the trait have specific data with the same name (non-abstract attributes - abstract ones can be overridden), an error conflict will be reported
If the attribute is val, a new object can be created in the class for assignment change 
If the attribute is var, it is not allowed and an error will be reported

Trait Overlay:

        
        Since a class can mix in (mixin ) multiple traits , and traits can have specific attributes and methods, if mixed
With the same method (method name, parameter list, return value are all the same) in the traits, there will inevitably be inheritance conflicts.
There are two types of conflicts:
(1) In the first type, two traits ( TraitA , TraitB ) mixed into a class ( Sub ) have the same concrete method, and
There is no relationship between the two traits . To solve this kind of conflict problem, directly override the conflicting method in the class ( Sub ).
(2) The second type, two traits ( TraitA , TraitB ) mixed into a class ( Sub ) have the same concrete method, and
Two traits inherit from the same trait ( TraitC ), and the so-called "diamond problem", to solve this kind of conflict problem, Scala
A strategy of trait stacking was adopted .
Diamond Question Test:
package chapter04
object Test11_TraitMinxin2 {
  def main(args: Array[String]): Unit = {
    val person1 = new Person12
    println(person1.Info())
  }
}
trait Age12{
val age:Int
  def Info()="age "
}
//下边两个特质均继承自Age12
trait Young12 extends Age12{
  override val age: Int = 12
  override def Info(): String = super.Info()+"Young "
}
trait Old12 extends  Age12{
  override val age: Int = 13
  override def Info(): String = super.Info()+"Old12 "
}
//钻石效应
class Person12 extends Young12 with  Old12 {
  override def Info(): String = super.Info()+"Person12 "
}

Test Results:

 The above results show that when a diamond problem is generated, it will be called in a sorted order according to the inheritance relationship

When we only want to call the method of a certain class, we can specify the inherited class

The Person12 class has been modified:

class Person12 extends Young12 with  Old12 {
  override def Info(): String = super[Young12].Info()+"Person12 "
}

Results of the:

The difference between traits and abstract classes:

1. Prioritize the use of traits. It is convenient for a class to extend (inherit) multiple traits, but only one abstract class.
2. If you need constructor parameters, use abstract classes. Because abstract classes can define constructors with parameters ,
   Traits don't work (only parameterless constructs).
Object Oriented Extensions:
(1) Type checking and conversion
When using polymorphism, the unique method of the subclass cannot be called, so a mandatory type conversion is required (in Scala, the method is used for mandatory type conversion)
Code sample:
package chapter04
object Test_14_Rxtends {
  def main(args: Array[String]): Unit = {
//多态
    var son:father14 =new son14
    val son1: son14 = son.asInstanceOf[son14]
    son1.sayHi()
  }
}
class father14{
}
class son14 extends father14 {
def sayHi(): Unit ={
  println("hi son")
}
}

Guess you like

Origin blog.csdn.net/m0_61469860/article/details/130116663