Java reuse class, polymorphic

Keywords: github Java Linker C

Reuse class

There are two ways to reuse code:

  • Combination: only the objects of the existing class need to be generated in the new class. The new class is composed of the objects of the existing class, that is, the object reference can be placed in the new class
  • Inheritance: create a new class according to the type of an existing class without changing the form of an existing class, take the form of an existing class and add new code to it

How to choose between inheritance and combination:

According to the author's understanding: for example, a person is an instance (object) of human beings, which is created by the class of human beings. The class of human beings has eyes, hair and other objects. The existence of this form is combination, and the son of this person is inheritance.

Note: there must be a parent class for each class in inheritance, which may be an explicitly inherited parent class or an implicitly inherited Object class (Java is single inheritance)

super keyword

The subclass calls the constructor of the parent class for necessary initialization (note that it should be written in the first line). In general, the constructor of a subclass will call the nonparametric constructor of the parent class by default. Therefore, if the parent class has no nonparametric constructor (forget to write, only write the one with parameters, or take the constructor private), the compiler will report an error

Call the method of the parent class. Because the child class automatically inherits the non private method of the parent class, if you override the method of the parent class (or customize other methods) and need to call the method of the parent class, you can use the super keyword

package test;

/**
 * @author Cheng Xi
 * @date 2020/1/29 0029 - 9:21
 * @contact:https://github.com/chengxi0
 */
public class SuperKeyword {

}
class Aa{
    private String name ;
    private int age ;

    //Remember to write the default constructor, unless you don't want to create the object as a nonparametric
    public Aa() {
    }

    //Construction method with two parameters
    public Aa(String  name , int age ) {
        this.name = name ;
        this.age = age ;
    }

    public void aaMethod() {
        System.out.println("Method of parent class");
    }
}

class Bb extends Aa{
    //Add another member property to the subclass
    private String hobby ;

    public Bb() {
        
    }

    //Call the super keyword, pass in the corresponding parameter, and use the constructor of the parent class to initialize
    public Bb(String name , int age  , String hobby) {
        super(name, age);
        //Reinitialize the newly defined properties of subclasses
        this.hobby = hobby ;
    }

    @Override
    public void aaMethod() {
        //Call the method of the parent class
        super.aaMethod();
        System.out.println("Subclass method");
    }

}

polymorphic

Polymorphism: the elimination of coupling between types, allowing it to treat an object as its own type or base class type.

Upward Transformation: the parent class reference points to the child class object, and the child class type is automatically promoted to the parent class type, which is safe.

Downward Transformation: Generally speaking, it is difficult to determine the specific type information of downward transformation, so we must use a special operation to obtain a safe downward transformation. Generally, we use brackets to fill in the desired type. If not, a type conversion exception will be returned.

Method call binding: associate a method call with a method body to become a method binding.

  • Pre binding: for example, C language, binding is performed before the program is executed, which is implemented by compiler and linker
  • Runtime binding (late binding): binding at runtime based on the type of object

The following code will illustrate a typical example of polymorphism:

 

package test;

import java.util.Random;

/**
 * @author Cheng Xi
 * @date 2020/1/29 0029 - 16:37
 * @contact:https://github.com/chengxi0
 */
public class Shapes {
    private static RandomShapeGenerator gen = new RandomShapeGenerator();
    public static void main(String[] args) {
        Shape[] s = new Shape[9];
        for (int i = 0; i < s.length; i++) {
            s[i] = gen.next();
        }
        for (Shape shape : s) {
            shape.draw();
        }
    }
}
class Shape{
    public void draw() {
        System.out.println("Parent painting");
    }

    public void erase() {
        System.out.println("Parent erasure");
    }
}

class Circle extends Shape{
    @Override
    public void draw() {
        System.out.println("circle");
    }
    @Override
    public void erase() {
        System.out.println("Erase circles");
    }
}

class Square extends Shape{
    @Override
    public void draw() {
        System.out.println("Picture box");
    }
    @Override
    public void erase() {
        System.out.println("Erase box");
    }
}

class Triangle extends Shape{
    @Override
    public void draw() {
        System.out.println("Draw triangle");
    }
    @Override
    public void erase() {
        System.out.println("Erase triangle");
    }
}

//It is a factory class, which randomly returns a reference of shape type through the next method
class RandomShapeGenerator {
    private Random rand = new Random(47);

    public Shape next() {
        switch (rand.nextInt(3)) {
            default:
            case 0 : return  new Circle() ;
            case 1 : return  new Square();
            case 2 : return  new Triangle();
        }
    }
}

Note:

  • If the parent class is a private method, then we will rewrite the private method in the process of inheritance. We don't call it rewrite anymore. The private method of the parent class is actually implicitly decorated by final. Therefore, the method in the child class is actually a newly defined method in the child class, although it is the same as the method of the parent class. That is, this method is not polymorphic, because it is unique among subclasses.
  • If a method or domain is modified by static, its behavior is not polymorphic. Because static methods and static fields are related to classes, not objects.

Inheritance and cleanup

  • In general, you should clean up the exported class first, then the base class. This is because the clean-up of the exported class may call some methods in the base class, so some components in the base class should still work and should not be destroyed prematurely. The order of destruction is the reverse of the order of initialization.
  • However, the following code will show that the members to be destroyed exist in the sharing of one or more other objects. At this time, it is not simply the opposite order to destroy them. Because we may destroy objects that need to be used by other objects, we need to count the destroyed objects.
package test;

/**
 * @author Cheng Xi
 * @date 2020/1/29 0029 - 17:23
 * @contact:https://github.com/chengxi0
 */
public class ReferenceCounting {
    public static void main(String[] args) {
        Shared shared = new Shared();
        //Each element of the comparing array shares a shared object
        //Therefore, the shared object cannot be destroyed directly when it is destroyed, because it is also destroyed by
        //Other comparing objects are shared, so all comparing objects should be used
        //Destroy all and then destroy the shared object
        Compassing[] compassing = {new Compassing(shared), new Compassing(shared),
                new Compassing(shared), new Compassing(shared), new Compassing(shared)};

        for (Compassing c : compassing) {
            c.disPose();
        }
    }
}

class Shared {
    private int refCount ;
    private static long  counter ;
    private final  long  id = counter++ ;

    public Shared() {
        System.out.println("Establish" + this);
    }

    public void addRef() {
        refCount++ ;
    }

    public void disPose() {
        //Every time you call the dispose method, you need to subtract 1 from refCount
        //Only when the number of objects associated with it is 0 can it be destroyed
        if (--refCount == 0) {
            System.out.println("Destruction:" + this);
        }
    }

    @Override
    public String toString() {
        return "shared : " + id ;
    }
}

class Compassing{
    private Shared shared ;
    private static long counter ;
    private final long id = counter++ ;

    public Compassing(Shared shared) {
        System.out.println("Establish"+ this) ;
        this.shared = shared ;
        shared.addRef() ;
    }

    public void disPose() {
        //Destroy the exported class first, then the base class object
        System.out.println("Destruction:" + this);
        //If the object associated with shared is not 0, it will not be destroyed
        shared.disPose();
    }

    @Override
    public String toString() {
        return "Compassing" + id ;
    }
}

Note:

  • It's good to understand the logic of the code and ensure that when multiple objects are associated, all the associated objects are destroyed before destroying the object. And every time you create a comparing object and share the shared object, remember to call the addRef() method to add 1 to the refcount property of the shared object
  • Learn how to use the id in the code, that is, each object has a corresponding id. use a counter of static long type, plus a counter of final long type + +, so that each object's id is unique, and know the order of creation.

 

 

 

 

 

 

Published 6 original articles, won praise 1, visited 73
Private letter follow

Posted by Transwarp-Tim on Wed, 29 Jan 2020 02:43:19 -0800