An example of polymorphism in Java from the book Java Philosophy

    public class Example {
        public static void main(String[] args) {

            Circle circle = new Circle();
            Triangle triangle = new Triangle();
            Line line = new Line();

            circle.doSomething(circle); //круг
            triangle.doSomething(triangle); //треугольник
            line.doSomething(line); //линия
        }
}

Class Line

public class Line extends Shape {

}

Class Circle

public class Circle extends Shape {

}

Class Triangle

public class Triangle extends Shape  {

}

Class Shape / / Shape

public class Shape {

    public void erase() {
        System.out.println("Cтирать");
    }

    public void draw() {
        System.out.println("Рисовать");
    }

    void doSomething(Shape shape) {
        shape.erase();
        shape.draw();
    }
}

The entire example in the book is not described, so I created everything myself by looking at the example in the book. Please check if it is correct?
Do I need to move the methods: erase, draw to a separate interface in this particular example?
This is polymorphism, since we use the type and parameter of the Shape class in the Shape shape method and we don't care what shape it is what is the parameter?

3 answers

As you have already been told in here, you need to redefine the methods for each class of the descendant.

However, the Shape class may not have these methods at all and may not implement them in any way. Why? Everything is simple, because each shape can implement drawing in its own way: to draw a circle, you need to know its center and radius, for a rectangle, you usually use the coordinates of the upper-left corner and its dimensions (width + height). And no one says that the figures must be only two-dimensional (but what about spheres, cubes, ellipsoids, hyperboloids, etc... they are all drawn much more complicated). The Shape class simply cannot know and implement all kinds of redraws of all possible shapes.

There are interfaces for this. You can use them to tell the program that some entity (in our case, a shape) can do something (in our case, it can be erased and drawn), but not know exactly how it will do it.

import java.util.ArrayList;

/*
 * Интерфейсы, показывающие "что мы можем делать"
 */
interface Drawable {
    void draw();
}

interface Eraseable {
    void erase();
}

/*
 * абстрактный класс фигуры
 * участок кода `implements Drawable, Eraseable` якобы говорит, что
 * "Фигура умеет рисоваться и стираться",
 * но фигура сама по себе не знает, КАК ИМЕННО она это будет делать
 */
abstract class Shape implements Drawable, Eraseable {
    public void doSomething() {
        erase();
        draw();
    }
}

/*
 * Классы конкретных фигур, которые "говорят" программе, 
 * КАК ИМЕННО они будут рисоваться и стираться
 */
class Triangle extends Shape {
    public void draw() {
        System.out.println("Triangle::draw");
    }

    public void erase() {
        System.out.println("Triangle::erase");
    }
}


class Circle extends Shape {
    public void draw() {
        System.out.println("Circle::draw");
    }

    public void erase() {
        System.out.println("Circle::erase");
    }
}

/*
 * И самое вкусное в классе Main
 */
public class Main
{
    public static void main(String[] args) {
        // список каких-то фигур.. мы не знаем, каких. Нам все равно.
        // мы просто знаем, что у нас есть фигуры
        ArrayList<Shape> list_of_shapes = new ArrayList();

        // добавляем конкретные фигуры в список "каких-то" фигур
        list_of_shapes.add(new Circle());
        list_of_shapes.add(new Triangle());
        list_of_shapes.add(new Circle());

        // работаем со списком, не задумываясь, КАКИЕ ИМЕННО у нас фигуры
        for (Shape shape : list_of_shapes) {
            shape.doSomething();
        }

        System.out.println("CLOSE PROGRAM");

        for (Shape shape : list_of_shapes) {
            shape.erase();
        }
    }
}

In as a result, we get the following output to the screen (note that the methods of the Circle and Triangle classes are called, although {[2] is listed in the loop]}):

Circle::erase
Circle::draw
Triangle::erase
Triangle::draw
Circle::erase
Circle::draw
CLOSE PROGRAM
Circle::erase
Triangle::erase
Circle::erase

However, the logical question is: what is the polymorphism here? After all, the question was about him. Note the main method. The most charming thing is that in the list of some shapes we add specific shapes (circles and triangles). An example is a vector graphics editor. The user has sketched some notes in the editor window. shapes. We don't know which ones. And at the stage of writing the program, we can't know. However, when closing the program, we need to delete all the shapes, erase them. The main method demonstrates how you can call methods of specific classes without knowing which class it is.

This is basically the whole point of polymorphism (polymorphism: from the Greek πολὺ - - a lot, and μορφή - form, or in Russian "multiform"). Using the knowledge that we are working with with the figure, we substitute a figure of a specific shape there.

 3
Author: Bogdan, 2019-01-30 10:02:39

You need to redefine the erase() and draw () methods in each descendant.

Yes, this is polymorphism, depending on the type that you pass to the doSomething() method, the corresponding implementation of the erase() and draw () methods will be selected.

public abstract class Shape {
    abstract void erase();
    abstract void draw();
}

public class Circle extends Shape {
    void erase() {
        System.out.println("Circle");
    {
    void draw() {
        System.out.println("DrawCircle");
    }
}

Similarly for other heirs.

 3
Author: Vennic, 2019-01-30 07:06:32

If by the book, it should be something like this

public class Main {

    public static void main(String[] args) {
        Circle circle = new Circle();
        Triangle triangle = new Triangle();
        Line line = new Line();

        doSomething(circle); // круг
        doSomething(triangle); // треугольник
        doSomething(line); // линия
    }

    private static void doSomething(Shape shape) {
        shape.erase(); // стереть
        shape.draw(); // нарисовать
    }
}

class Shape {

    public void erase() {
        System.out.println("Shape - erase");
    }

    public void draw() {
        System.out.println("Shape - draw");
    }
}

class Circle extends Shape {

    public void erase() {
        System.out.println("Circle - erase");
    }

    public void draw() {
        System.out.println("Circle - draw");
    }
}

class Triangle extends Shape {

    public void erase() {
        System.out.println("Triangle - erase");
    }

    public void draw() {
        System.out.println("Triangle - draw");
    }
}

class Line extends Shape {

    public void erase() {
        System.out.println("Line - erase");
    }

    public void draw() {
        System.out.println("Line - draw");
    }
}
 1
Author: Олексій Моренець, 2019-01-30 19:33:46