Создание собственных классов в Java (продолжение), класс Object

Рассмотрим пример класса точек на плоскости:

class Point {
    public double x; // абсцисса точки
    public double y; // ордината точки

    // возвращает строку с описанием точки
    public String toString() {
        return "("+x+";"+y+")";
    }
    // выводит на экран описание точки
    public void printPoint() {
        System.out.print(this.toString());
    } 
    // метод перемещает точку на указанный вектор
    public void movePoint(double a, double b) {
        x = x + a;
        y = y + b;
    }
    // метод изменяет координаты точки на указанные
    public void setPoint(double a, double b) {
        x = a;
        y = b;
    } 
    // конструктор по умолчанию, создающий точку в начале координат
    public Point() {
        x = 0.0;
        y = 0.0;
    }
    // конструктор, создающий точку с указанными координатами
    public Point(double a, double b) {
        x = a;
        y = b;
    }  
    // метод вычисляющий расстояние между точками
    public double length(Point p) {
        return Math.sqrt( Math.pow(p.x-x,2) + Math.pow(p.y-y,2) );
    }
    // метод проверяющий совпадают ли точки
    public boolean equalsPoint(Point p) {
        if(this.x == p.x && this.y == p.y) {
            return true;
        } else {
            return false;
        }
    }    
}

public class Main {
    public static void main(String[] args) {
        Point p1 = new Point();
        Point p2 = new Point(1,1);
        System.out.println("Растстояние между точками "+p1+" и "+p2+" равно "+p1.length(p2));
    }
}

В этом классе создаётся отдельный метод toString(), предназначенный для представления каждого объекта в виде строки. Этот метод можно использовать для собственных нужд (например, он вызывается в методе printPoint(), печатающем строку на экран), но кроме этого метод toString() будет вызываться автоматически, когда возникнет попытка автоприведения объекта к строковому типу.

Например, мы можем пользоваться методом явно:

Point p3 = new Point(3,4.67);
System.out.println("Координаты точки: "+p3.toString());

А можем просто обединять наш объект с другой строкой, провоцируя автоприведение:

Point p4 = new Point(3.2,2.3);
System.out.println("Координаты точки: "+p4);

Результат при этом будем получать идентичный.

Такой особенный метод toString() существует на самом деле для всех объектов в Java. Любой класс в Java является наследниом класса Object (хотя наследование мы явно при создании своего класса никак не используем) и от этого родительского класса получает ряд готовых методов (среди которых toString() тоже присутствует). Теперь в классе Point мы метод toString() перегрузили, сделав для него такую реализацию, которая требуется нам в нашей программе.

Ещё один яркий пример метода, наследуемого от коренного класса Object — это метод equals(Object o) для сравнения объектов — его можно применять к любым двум объектам (даже если они из разных классов), вызывая метод для одного из них, а второй передавая через параметр. Метод будет возвращать истинное значение тогда и только тогда, когда будет вызван для двух ссылок на один и тот же объект. В своих программах с практической точки зрения равными можно считать разные объекты имеющие одинаковый набор текущих значений в полях, поэтому метод equals обычно тоже перегружают. Вместе с ним обязательно перегружать и метод hashCode(), возвращающий некоторое целое число для каждого объекта, являющегося его уникальным числовым идентификатором (хешем). По умолчанию (в той реализации, которая представлена в классе Object) это число строится на основании адреса объекта в памяти, но при перегрузке метода можно придумать свою собственную реализацию, главное, чтобы она удовлетворяла одному важному правилу: если два обекта совпадают в соответствии с методом equals, то у них должны быть одинаковые хеши, возвращаемые методом hashCode(), при этом обратного не требуется. Например, для нашего класса Point мы могли бы в качестве хеша возвращать произведение координат точки.

Не требуется, но рекомендуется для своих классов перегружать перечисленные выше методы. В примере это сделано для метода toString, но не сделано для equals и hashCode.

Задачи

  1. Создайте в классе метод, который будет выводить на экран сообщение о том, в какой координатной четверти лежит точка.
  2. Создайте в классе метод, проверяющий, являются ли две точки симметричными относительно начала отсчёта.
  3. Измените в классе конструктор по умолчанию таким образом, чтобы начальные координаты точки при её создании пользователь задавал с клавиатуры.
  4. Создайте в классе метод, проверяющий, являются ли три точки коллинеарными (т.е. лежащими на одной прямой).
  5. Вместо представленного метода equalsPoint перегрузите в классе методы equals и hashCode.