Javanese Online

Класс Object, метод toString, наследование реализации, @Override

Возьмём для примера объект класса Nokia3310. Если попытаться представить его как строку, результат будет выглядеть печально:

System.out.println("мой телефон: " + new Nokia3310("valmistusnumero"));
// мой телефон: Nokia3310@4b67cf4d

На объекте был неявно вызван метод toString(), определённый в классе Object:

package java.lang;

/**
 * Class {@code Object} is the root of the class hierarchy.
 * Every class has {@code Object} as a superclass. All objects,
 * including arrays, implement the methods of this class.
 *
 * @author  unascribed
 * @see     java.lang.Class
 * @since   JDK1.0
 */
public class Object {

    ...

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

Nokia3310, как и все остальные классы, неявно наследует класс Object. Это значит, что методы и поля, которые объявлены в Object, доступны также и в Nokia3310. Это явление (наследование классов) называется наследованием реализации (implementation inheritance).

Чтобы сделать результат приведения Nokia3310 к строке более осмысленным, нужно переопределить метод toString().

public final class Nokia3310 implements MobilePhone {

    ...

   public String toString() {
        return "Nokia3310(заряжен на " + getChargePercentage() + "%)";
    }
}

Снова попробуем привести к строке:

мой телефон: Nokia3310(заряжен на 42%)

Переопределение toString() считается хорошим тоном, т. к. помогает при отладке кода. В toString() крайне желательно упоминать все поля, например, так:

public String toString() {
    return "Nokia3310(IMEI=" + imei +
            ", serialNumber=" + serialNumber +
            ", batteryVoltage=" + batteryVoltage + ")";
}
// мой телефон: Nokia3310(IMEI=7660895798011981084, serialNumber=valmistusnumero, batterVoltage=3.8)

Аннотация @Override

Порой мы делаем опечатки. Например, если написать asString вместо toString, получится метод, который не переопределяет toString.

Аннотация @Override гарантирует, что описанный после неё метод переопределяет метод родителя.

Эта аннотация должна стоять на всех методах, которые переопределяют методы родительского класса или интерфейса:

public final class Nokia3310 implements MobilePhone {

    ...

    @Override
    public void dial(String number) {
        ...
    }

    @Override
    public int getChargePercentage() {
        ...
    }

    @Override
    public String toString() {
        ...
    }

}

Если же попытаться переопределить метод, которого в суперклассе нет, аннотация @Override поможет сразу же найти ошибку:

Override негодует

Наследование реализации

К сожалению, Как показано выше, Java позволяет классам наследовать классы. Таким образом, класс может иметь как собственные, явно определённые, так и унаследованные методы и поля.

Всё, что хочется сказать о наследовании классов, — что это достаточно ненадёжная техника. Подробнее — см. Joshua Bloch, Effective Java, 2nd Edition, Item 16 'Favor composition over inheritance'.

Комментарии к уроку

Сообщить об ошибке

Javanese.Online в GitHub

Чаты и каналы в Telegram

RSS-лента