Рассмотрим пример класса точек на плоскости:
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.
Задачи
- Создайте в классе метод, который будет выводить на экран сообщение о том, в какой координатной четверти лежит точка.
- Создайте в классе метод, проверяющий, являются ли две точки симметричными относительно начала отсчёта.
- Измените в классе конструктор по умолчанию таким образом, чтобы начальные координаты точки при её создании пользователь задавал с клавиатуры.
- Создайте в классе метод, проверяющий, являются ли три точки коллинеарными (т.е. лежащими на одной прямой).
- Вместо представленного метода equalsPoint перегрузите в классе методы equals и hashCode.
«…в классе Point мы метод toString() перегрузили…»
Перегрузили или переопределили? Входные данные, что для Object.toString(), что для нашего Point.toString() одинаково отсутствуют. Значит, нет условия, по которому компилятор будет выбирать нужный метод, всегда будет использоваться наш. Или я чего-то не понимаю?
В статье описка — правильно говорить что toString() переопределили. Аннотация @Override отсутствует потому что она является опциональной.