Java programming logic (15) - inheritance and polymorphism acquaintance

inherit

We talked about in the previous section, the concept of mapping the reality of the concept of the program, we talk about the combination between class and class, between the concept of reality there is a very important relationship, that is, the classifier has a root, then continue to refine down to form a hierarchical classification system. This example is very much:

In the natural world, there are biological animals and plants, animals have different subjects, carnivores, herbivores, omnivores and other predators are wolves, dogs, tigers, etc., which are divided into different varieties ...

Open electricity supplier site, in general classification list in a prominent position, such as household appliances, clothing, clothing has a women's, men, men have shirts, jeans and so on ...

The computer program often come to represent the relationship between the classification of objects using inheritance relationships between classes. In the hierarchy, there is a parent and child classes, such as dogs and animal Animal Dog, Animal is the parent class, Dog is a subclass. Also called parent base class, subclass, also called a derived class, the subclass is the parent class opposite, class B may be a subclass of the class A and class C is the parent class.

It is called inheritance because the subclass inherits the properties and behavior of the parent, the parent class attributes and behavior of some sub-class has. But subclass can increase subclass-specific attributes and behaviors, some parent class, some behaviors, implementation subclass may not be exactly the same as the parent class.

Using inheritance on the one hand can reuse the code, public properties and behavior can be placed in the parent class, and subclass-specific subclass only need to focus on it, on the other hand, objects of different subclasses can be more convenient unified treatment.

This section is mainly to introduce inheritance in Java graphics processing by some simple examples, will introduce the basic concepts of inheritance, inheritance more in-depth discussion and implementation principle, we introduce in the following sections.

Object

In Java, all classes have a parent, even if the parent does not declare, there is an implicit parent, the parent class called Object. Object attributes are not defined, but the definition of a number of methods, as shown below:


In this section we will introduce toString () method, otherwise we will be gradually introduced in the following sections. Objective toString () method returns an object that is a text description of this method can be directly used for all classes.

For example, for the Point class we introduced earlier, so you can use the toString method:

Point p = new Point(2,3);
System.out.println(p.toString()); 

Output like this:

Point@76f9aa66

What does it mean? Before the @ is the class name after the @ What is it? We look at the toString code:

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

getClass (). getName () returns the current object's class name, hashCode () returns an object hash value, the hash we will introduce in later chapters, here it can be understood as an integer that by default, usually the memory address value of the object, Integer.toHexString (hashCode ()) returns the hash value in hexadecimal notation.

Why you wrote it? Write the class name is understandable, represents the type of object, and write hash value is a last resort, because the Object class does not know the specific object properties, do not know how to use a text description, but need to distinguish between different objects, can only write a hash value.

But subclass is aware of methods of the parent class, subclass own properties can be rewritten to reflect their different implementations. The so-called rewrite, is the same as the parent class definition and method, and reimplemented.

Point class - override toString ()

Let us look at the Point class, this time we rewrite the toString () method.

Copy the code
public class Point {
    private int x;
    private int y;
    
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public double distance(Point point){
        return Math.sqrt(Math.pow(this.x-point.getX(),2)
                +Math.pow(this.y-point.getY(), 2));
    }
    
    public int getX() {
        return x;
    }
    
    public int tide () {
        return y;
    }

    @Override
    public String toString() {
        return "("+x+","+y+")";
    }
}
Copy the code

A front @Override toString method, which means that this method is a method toString parent class rewritten, the rewritten method returns the value of Point x and y coordinates. After rewriting, the call implementation subclass. For example, the following code output becomes: (2,3)

Point p = new Point(2,3);
System.out.println(p.toString());

Graphics processing class

Next, we further explained with examples of some of the graphics processing, first look at the figures:

 

These are some of the basic pattern, a wired pattern, square, triangular, circular, etc., have a different color pattern. Next, we define the following class to demonstrate some of the concepts of inheritance:

  • Parent class Shape, a graphical representation.
  • Class Circle, represents the circle.
  • Class Line, represent a straight line.
  • Class ArrowLine, the straight line with an arrow indicates. 

Graphics (Shape)

All graphical representation has a color attribute, a method of drawing representation, the following is the code:

Copy the code
public class Shape {
    private static final String DEFAULT_COLOR = "black";
    
    private String color;
    
    public Shape() {
        this(DEFAULT_COLOR);
    }

    public Shape(String color) {
        this.color = color;
    }
    
    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
    
    public void draw(){
        System.out.println("draw shape");
    }
}
Copy the code

以上代码基本没什么可解释的,实例变量color表示颜色,draw方法表示绘制,我们不会写实际的绘制代码,主要是演示继承关系。

圆 (Circle)

圆继承自Shape,但包括了额外的属性,中心点和半径,以及额外的方法area,用于计算面积,另外,重写了draw方法,代码如下:

Copy the code
public class Circle extends Shape {
    //中心点
    private Point center;
    
    //半径
    private double r; 

    public Circle(Point center, double r) {
        this.center = center;
        this.r = r;
    }

    @Override
    public void draw() {
        System.out.println("draw circle at "
                +center.toString()+" with r "+r
                +", using color : "+getColor());    
    }
    
    public double area(){
        return Math.PI*r*r;
    }
}
Copy the code

说明几点:

  • Java使用extends关键字标明继承关系,一个类最多只能有一个父类。
  • 子类不能直接访问父类的私有属性和方法,比如,在Circle中,不能直接访问shape的私有实例变量color。
  • 除了私有的外,子类继承了父类的其他属性和方法,比如,在Circle的draw方法中,可以直接调用getColor()方法。 

看下使用它的代码:

Copy the code
public static void main(String[] args) {
    Point center = new Point(2,3);
    //创建圆,赋值给circle
    Circle circle = new Circle(center,2);
    //调用draw方法,会执行Circle的draw方法
    circle.draw();
    //输出圆面积
    System.out.println(circle.area());
}
Copy the code

程序的输出为:

draw circle at (2,3) with r 2.0, using color : black
12.566370614359172

这里比较奇怪的是,color是什么时候赋值的?在new的过程中,父类的构造方法也会执行,且会优先于子类先执行。在这个例子中,父类Shape的默认构造方法会在子类Circle的构造方法之前执行。关于new过程的细节,我们会在后续章节进一步介绍。

直线 (Line)

线继承自Shape,但有两个点,有一个获取长度的方法,另外,重写了draw方法,代码如下:

Copy the code
public class Line extends Shape {
    private Point start;
    private Point end;
    
    public Line(Point start, Point end, String color) {
        super(color);
        this.start = start;
        this.end = end;
    }

    public double length(){
        return start.distance(end);
    }
    
    public Point getStart() {
        return start;
    }

    public Point getEnd() {
        return end;
    }
    
    @Override
    public void draw() {
        System.out.println("draw line from "
                + start.toString()+" to "+end.toString()
                + ",using color "+super.getColor());
    }
}
Copy the code

这里我们要说明的是super这个关键字,super用于指代父类,可用于调用父类构造方法,访问父类方法和变量:

  • 在line构造方法中,super(color)表示调用父类的带color参数的构造方法,调用父类构造方法时,super(...)必须放在第一行。
  • 在draw方法中,super.getColor()表示调用父类的getColor方法,当然不写super.也是可以的,因为这个方法子类没有同名的,没有歧义,当有歧义的时候,通过super.可以明确表示调用父类的。
  • super同样可以引用父类非私有的变量。

可以看出,super的使用与this有点像,但super和this是不同的,this引用一个对象,是实实在在存在的,可以作为函数参数,可以作为返回值,但super只是一个关键字,不能作为参数和返回值,它只是用于告诉编译器访问父类的相关变量和方法。

带箭头直线 (ArrowLine)

带箭头直线继承自Line,但多了两个属性,分别表示两端是否有箭头,也重写了draw方法,代码如下:

Copy the code
public class ArrowLine extends Line {
    
    private boolean startArrow;
    private boolean endArrow;
    
    public ArrowLine(Point start, Point end, String color, 
            boolean startArrow, boolean endArrow) {
        super(start, end, color);
        this.startArrow = startArrow;
        this.endArrow = endArrow;
    }

    @Override
    public void draw() {
        super.draw();
        if(startArrow){
            System.out.println("draw start arrow");
        }
        if(endArrow){
            System.out.println("draw end arrow");
        }
    }
}
Copy the code

ArrowLine继承自Line,而Line继承自Shape,ArrowLine的对象也有Shape的属性和方法。

注意draw方法的第一行,super.draw()表示调用父类的draw()方法,这时候不带super.是不行的,因为当前的方法也叫draw()。

需要说明的是,这里ArrowLine继承了Line,也可以直接在类Line里加上属性,而不需要单独设计一个类ArrowLine,这里主要是演示继承的层次性。

图形管理器

使用继承的一个好处是可以统一处理不同子类型的对象,比如说,我们来看一个图形管理者类,它负责管理画板上的所有图形对象并负责绘制,在绘制代码中,只需要将每个对象当做Shape并调用draw方法就可以了,系统会自动执行子类的draw方法。代码如下:

Copy the code
public class ShapeManager {
    private static final int MAX_NUM = 100;
    private Shape[] shapes = new Shape[MAX_NUM];
    private int shapeNum = 0;
    
    public void addShape(Shape shape){
        if(shapeNum<MAX_NUM){
            shapes[shapeNum++] = shape;    
        }
    }
    
    public void draw(){
        for(int i=0;i<shapeNum;i++){
            shapes[i].draw();
        }
    }
}
Copy the code

ShapeManager使用一个数组保存所有的shape,在draw方法中调用每个shape的draw方法。ShapeManager并不知道每个shape具体的类型,也不关心,但可以调用到子类的draw方法。

我们来看下使用ShapeManager的一个例子:

Copy the code
public static void main(String[] args) {
    ShapeManager manager = new ShapeManager();
    
    manager.addShape(new Circle(new Point(4,4),3));
    manager.addShape(new Line(new Point(2,3),
            new Point(3,4),"green"));
    manager.addShape(new ArrowLine(new Point(1,2), 
            new Point(5,5),"black",false,true));
    
    manager.draw();
}
Copy the code

新建了三个shape,分别是一个圆、直线和带箭头的线,然后加到了shape manager中,然后调用manager的draw方法。

需要说明的是,在addShape方法中,参数Shape shape,声明的类型是Shape,而实际的类型则分别是Circle,Line和ArrowLine。子类对象赋值给父类引用变量,这叫向上转型,转型就是转换类型,向上转型就是转换为父类类型。

变量shape可以引用任何Shape子类类型的对象,这叫多态,即一种类型的变量,可引用多种实际类型对象。这样,对于变量shape,它就有两个类型,类型Shape,我们称之为shape的静态类型,类型Circle/Line/ArrowLine,我们称之为shape的动态类型。在ShapeManager的draw方法中,shapes[i].draw()调用的是其对应动态类型的draw方法,这称之为方法的动态绑定。

为什么要有多态和动态绑定呢?创建对象的代码 (ShapeManager以外的代码)和操作对象的代码(ShapeManager本身的代码),经常不在一起,操作对象的代码往往只知道对象是某种父类型,也往往只需要知道它是某种父类型就可以了。

可以说,多态和动态绑定是计算机程序的一种重要思维方式,使得操作对象的程序不需要关注对象的实际类型,从而可以统一处理不同对象,但又能实现每个对象的特有行为。后续章节我们会进一步介绍动态绑定的实现原理。

小结

本节介绍了继承和多态的基本概念:

  • 每个类有且只有一个父类,没有声明父类的其父类为Object,子类继承了父类非private的属性和方法,可以增加自己的属性和方法,可以重写父类的方法实现。
  • new过程中,父类先进行初始化,可通过super调用父类相应的构造方法,没有使用super的话,调用父类的默认构造方法。
  • 子类变量和方法与父类重名的情况下,可通过super强制访问父类的变量和方法。
  • 子类对象可以赋值给父类引用变量,这叫多态,实际执行调用的是子类实现,这叫动态绑定。

But with regard to inheritance, there are many details, such as instance variables of the same name situation. In addition, although inheritance can reuse the code, to facilitate unified handling objects of different subclasses, but inheritance is in fact double-edged sword, improper use, there are a lot of problems. Let the next section to discuss these issues, and implement the principles of inheritance and polymorphism, let us discuss in the next section.

Guess you like

Origin www.cnblogs.com/ivy-xu/p/12383689.html