Considerations for the use of Java polymorphism

  • 2020-04-01 02:26:09
  • OfStack

How is Java polymorphism implemented?
Java polymorphism, like C++, is achieved by late binding, or runtime binding. When a method referenced by an object is called, the compiler does not know whether the reference refers to an object of the type described when the variable is declared or to a subclass of that type. So the compiler cannot bind to a specific method for this call. Only Runtime type identification (RTTI, Runtime type identification) in Java is bound to the specific method at Runtime. Here's a specific example:


class shape
{
    public void draw()
    {
   print("shape");
    }
}
class triangle extends shape
{
    public void draw()
    {
   print("triangle");
    }
}
public class Polymorphism {
public static void main(String[] args)
{
    shape s=new triangle();
    s.draw();
}

The result is a triangle
S is a shape reference, but the draw method of triangle is still called at runtime because it is a triangle object.

Some of the pitfalls of Java polymorphism

Override private methods?
You can't override private methods in Java, which makes sense because private methods are invisible to subclasses. Subclasses do not inherit private methods from their superclasses, let alone override them. So the method with the same name in a subclass is a completely new method.


public class Polymorphism {
    private void show()
    {
   print("show parent");
    }
public static void main(String[] args)
{
    Polymorphism p=new privateMethod();
    p.show();
}
}
class privateMethod extends Polymorphism
{
    public void show()
    {
   print("show derived");
    }
}

The result is show parent

Polymorphism of fields and static methods?
A subclass can inherit from a parent class's non-private fields. Are subclasses' fields also polymorphic? Let's look at a practical example:


class shape
{
    protected int perimeter=1;
    public void draw()
    {
   print("shape");
    }
    public int getPerimeter()
    {
   return perimeter;
    }
}
class triangle extends shape
{
int perimeter=3;
    public void draw()
    {
   print("triangle");
    }
    public int getPerimeter()
    {
   return perimeter;
    }
    public int getSuperPerimeter()
    {
   return super.perimeter;
    }
}
public class Polymorphism {

public static void main(String[] args)
{
    shape s=new triangle();
    print("s.perimeter:"+s.perimeter);
    print("s.getperimeter:"+s.getPerimeter());
    triangle t=new triangle();
    print("t.perimeter:"+t.perimeter);
    print("t.getperimeter:"+t.getPerimeter());
    print("t.getsuperperimeter:"+t.getSuperPerimeter());
}
}

Here are the results:
< img SRC = "border = 0 / / files.jb51.net/file_images/article/201311/20131114143445.jpg? 20131014143555 ">
This result contains the following information:
1. Direct field access after the triangle object is transformed upward into shape is determined by the compiler, so no polymorphism is shown and 1 is returned.
2. After the triangle object is transformed upward into shape, the method called to access the field is to call the getperimeter method of triangle according to the runtime object type with delayed binding, and the return is 3
The t object contains two perimeter fields, one from itself and one from its parent class. By default, when a field is called with the name of the field, its own perimeter field is returned. To call the field inherited from the parent class, the method super.perimeter is used.
This result seems somewhat confusing, and to avoid this, we generally declare the field private (a subclass cannot inherit), and it is best not to declare the field with the same name as the field inherited from the parent class.
Static methods are not polymorphic because static methods are bound to classes and there is no such thing as not knowing the type.

Constructor polymorphism?
Constructors are not polymorphic because the constructors themselves are static (if not, they fall into a chicken-and-egg loop). To introduce our problem, look at the order in which the constructor is called.
1. The storage space allocated for this object is initialized to 0 (object is initialized to null)
2. Constructor calls to the parent class (this ensures that fields accessed in the constructor of the subclass are initialized)
3. Initialization of member variables
4. Constructor calls for subclasses

Now suppose that in step 2, we call a method in the constructor of the superclass, is that method polymorphic? Let's look at a specific example:


class shape
{
    protected int perimeter=1;
    public shape()
    {
   draw();
   print("shape created");
    }
    public void draw()
    {
   print("draw shape "+perimeter);
    }

}
class triangle extends shape
{
int perimeter=3;
public triangle()
{
    print("triangle created");
}
    public void draw()
    {
   print("draw triangle "+perimeter);
    }
    public int getPerimeter()
    {
   return perimeter;
    }
}
public class Polymorphism {

public static void main(String[] args)
{
    shape s=new triangle();
}
}

Operation results:

 

We can see that although the triangle object is not yet constructed, the draw method is still a draw method that is dynamically bound to the triangle. Also notice that the value perimeter is not initialized to 3, but 0.

The result is that we access the fields of the triangle object before it is initialized. So in practice we want to avoid calling other methods in the constructor, or just calling private methods (which are not inherited and therefore do not cause this problem)


Related articles: