Освой программирование играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Методы

Перегрузка методов
Методы с переменным числом параметров
Метод toString()
Как вернуть из метода больше одного значения?

Класс может содержать методы - один, два, три и больше в зависимости от сложности класса. Название метода всегда завершается двумя круглыми скобками, после которых идет блок кода, обрамлённый фигурными скобками. Например, метод sayMeow() класса Cat выводит мяуканье кошки. Внутри имени метода могут быть параметры, например, sayMeow(3) - кошка мяукает три раза. Параметров может быть несколько, тогда они разделяются запятыми.

Общая форма объявления метода выглядит следующим образом:


модификатор тип имяМетода(список_параметров) {
    // тело метода
}

Метод может не иметь параметров, в этом случае используются пустые скобки. Модификатор определяет видимость метода (public, private). Если модификатор не указан, то считается, что метод имеет модификатор private в пределах своего пакета.

Методы могут вызывать другие методы.

Каждый метод начинается со строки объявления внутри круглых скобок, которую называют сигнатурой метода:

public static void sayMeow(int count) {
    // здесь ваш код
}

Если рассмотреть данный метод, то можно сказать следующее. Ключевое слово public означает, что метод доступен для любого класса. Ключевое слово static означает, что нам не нужно создавать экземпляр (копию) объекта Cat в памяти. Ключевое слово void означает, что метод не возвращает никаких данных. Именем метода является слово перед круглыми скобками.

Если метод возвращает какие-то данные, то в теле метода используется оператор return значение, где значение - это возвращаемое значение. Тогда вместо void нужно указать возвращаемый тип.

Вспомним наш класс Box, в котором определены высота, ширина и глубина ящика. Зная эти величины, мы вычисляли объём коробки самостоятельно. Но мы можем расширить возможности класса, чтобы он сам мог вычислить объём внутри класса и предоставить нам готовые данные. Давайте добавим в класс новый метод:


class Box {
    int width; // ширина коробки
    int height; // высота коробки
    int depth; // глубина коробки

    // вычисляем объём коробки
    String getVolume() {
        return "Объём коробки: " + (width * height * depth);
    }
}

Теперь пробуем вычислить объём коробки с помощью готового метода, который есть в классе:


Box catBox = new Box();

catBox.width = 400;
catBox.height = 200;
catBox.depth = 250;

mInfoTextView.setText(catBox.getVolume());

Мы уже не вычисляем объём вручную, за нас это сделает класс Box, у которого есть готовый метод для вычисления объёмов.

Обращение к методу осуществляется как и к переменной через точку. Наличие круглых скобок позволяет различать метод от имени переменной. То есть, если вы увидите запись:


cat.getVolume; // это переменная
cat.getVolume(); // это метод

Выше приведён немного искусственный пример, так как опытный программист никогда не назовёт переменную именем getVolume. Существует рекомендация, что для методов в начале имени нужно использовать глагол и начинаться имя должно с маленькой буквы - переменные так называть не следует.

Использование параметров

Параметры позволяют работать с различными данными. Допустим, мы хотим вычислить площадь прямоугольника со сторонами 3 и 5 см.


int getSquare() {
    return 3 * 5;
}

Метод работает, но область его применения слишком ограничена. Мы сможем вычислять площадь только одного прямоугольника с жёстко заданными размерами. Но прямоугольники бывают разными и нам нужен универсальный метод. Добиться решения задачи можно с помощью параметров. Перепишем метод следующим образом:


int getSquare(int a, int b) {
    return a * b;
}

Теперь мы можем вычислять площадь любого прямоугольника, зная его размеры. Возьмём тот же прямоугольник со сторонами 3 и 5 см и вычислим его площадь:


mInfoTextView.setText("Площадь прямоугольника: " + getSquare(3, 5));

В правильно написанных классах стараются избегать доступа к переменным класса напрямую. Следует использовать методы, которые позволяют избежать ошибок. В нашем классе Box использовались отдельные переменные width, height, depth. Код с использованием этих переменных слишком громоздкий, кроме того вы можете забыть про какую-нибудь переменную. Добавим в класс новый метод, который упростит наш код для вычисления объёма ящика:


package ru.alexanderklimov.test;

class Box {
    int width; // ширина коробки
    int height; // высота коробки
    int depth; // глубина коробки

    // вычисляем объём коробки
    int getVolume() {
        return width * height * depth;
    }
    
    // устанавливаем размеры коробки
    void setDim(int w, int h, int d) {
        width = w;
        height = h;
        depth = d;
    }
}

Пробуем класс в действии:


Box catBox = new Box();
catBox.setDim(400, 200, 250);
int vol = catBox.getVolume();

mInfoTextView.setText("Объём ящика: " + vol);

Теперь мы не обращаемся к отдельным переменным класса, а вызываем метод setDim() для установки размеров ящика, после чего можно вызвать метод getVolume() для вычисления объёма. Естественно, вы можете реализовать свою логику в классе. Например, вы можете создать метод getVolume() с параметрами, которые отвечают за размеры ящика и возвращать сразу готовый результат.

Перегрузка методов

Метод - имя для действия: прыгнуть, мяукнуть, отформатировать диск. Использование имён при написании кода упрощает её понимание и модификацию. Работа разработчика схожа с работой писателя - в обоих случаях требуется донести свою мысль до читателя/приложения.

Часто одно и то же слово имеет несколько разных значений - оно перегружено. Например, мы говорим "вымыть посуду" и "вымыть кота". Было бы глупо говорить "посудовымыть посуду" или "котовымыть кота", чтобы подчеркнуть разницу. Также и с методами. Можно создавать методы с одинаковыми именами, но с разным набором аргументов.

Перегрузку (overloading) следует отличать от замещения (overriding) - иной реализации метода в подклассе первоначально определившего метод класса.

Java, как и многие языки программирования, разрешает создавать внутри одно класса несколько методов с одним именем. Главное, чтобы у них различались параметры. Параметры могут различаться типами или количеством аргументов. Будьте внимательны, если вы зададите различные типы для возвращаемого значения, то этого будет недостаточно для создания перегруженной версии метода. Когда Java встречает вызов перегруженного метода, то выбирает ту версию, параметры которой соответствуют аргументам, использованным в вызове.

Создадим класс Cat с набором перегруженных методов:


class Cat {
    void meow() {
        // параметры отсутствуют
    }
    
    void meow(int count) {
        // используется один параметр типа int
    }
    
    void meow(int count, int pause) {
        // используются два параметра типа int
    }
    
    long meow(long time) {
        // используется один параметр типа long
        return time;
    }
    
    double meow(double time) {
        // используется один параметр типа double
        return time;
    }
}

Вы можете вызвать любой метод из класса:


Cat kitty = new Cat();
kitty.meow();
kitty.meow(3);
kitty.meow(3, 2);
kitty.meow(4500.25);

Если присмотреться, то можно догадаться, какая именно версия метода вызывается в каждом конкретном случае.

Аналогично, перегрузка используется и для конструкторов.

Методы с переменным числом параметров

Можно создавать методы с переменным числом параметров. В этом случае используется многоточие.


public static double getMaxValue(Object... args) {
    // код
}

По сути, создаётся массив типа Object[].

Создадим метод, вычисляющий и возвращающий максимальное из произвольного количества значений.


public static double getMaxValue(double... values) {
    double largest = Double.MIN_VALUE;
    for(double v : values) {
        if (v > largest) {
            largest = v;
        }
    }
    return largest;
}

Использование метода.


double variable = getMaxValue(5.3, 39.6, -4);

До Java 5 использовался следующий способ.


static void printArray(Object[] args) {
   ...
}

Подобный код может встречаться в старых проектах, но в Android практически не используется.

Метод toString()

Каждый класс реализует метод toString(), так как он определён в классе Object. Но использовать метод по умолчанию не слишком удобно, так как не содержит полезной информации. Разработчики предпочитают переопределять данный метод под свои нужды. Сам метод имеет форму:


String toString()

Вам остаётся возвратить объект класса String, который будет содержать полезную информацию о вашем классе. Давайте возьмём для примера класс Box, созданный выше:


class Box {
    int width; // ширина коробки
    int height; // высота коробки
    int depth; // глубина коробки
    
    Box(int width, int height, int depth){
    	this.width = width;
    	this.height = height;
    	this.depth = depth;
    }

    // вычисляем объём коробки
    String getVolume() {
        return "Объём коробки: " + (width * height * depth);
    }
    
    public String toString() {
        return "Коробочка для кота размером " + width + "x" + height + "x" + depth;
    }
}

Теперь можете узнать о классе Box:


Box box = new Box(4, 5, 6);
mInfoTextView.setText(box.toString());

Метод очень часто используется при создании собственных классов и вам тоже придётся прибегать к этому способу.

Как вернуть из метода больше одного значения?

Методы в Java возвращают одно значение. А если хочется сразу вернуть сразу два и более значений? Например, у нас имеется массив чисел и мы хотим написать метод, который сразу возвращает минимальное и максимальное значение из него.

Одно из решений заключается в том, что нужно "запаковать" два значения полученные в одном методе с помощью конструктора специального класса, а затем "распаковать" их в другом методе, при обращении к конструктору.

Реализация такого решения имеется в ответе на задачу на нахождение минимального и максимального значений в массиве.

Реклама