JavaRush /Java блог /Random UA /Методи в Java
Professor Hans Noodles
41 рівень

Методи в Java

Стаття з групи Random UA
Існує один цікавий принцип, про який багато хто чув. Він називається "Поділяй і володарюй". Цей принцип використовується у багатьох сферах людського життя, наприклад, у політиці. Він означає поділ великої кількості різнорідних частин у державі, розпалювання та використання ворожнечі між цими частинами. Іншими словами: створити конфлікт між тими, хто потенційно створює загрозу владі. Але ми з вами програмісти, тому нас цікавить виключно технічне трактування цього принципу. А звучить вона так: “Принцип “Поділяй і владарюй” полягає у розбитті великого завдання на дрібніші доти, доки вони не стануть елементарними. Потім потрібно послідовно вирішити їх і поєднати все в одну цілу систему. Ця програма повинна вирішувати поставлене завдання” Тобто, ви просто розбиваєте велике завдання на дрібніші, вирішити які вам не становить проблем. А потім збираєте рішення в одне велике. Щоб дотримуватися цього простого і корисного принципу, Java-програмування використовують методи. Методи в Java - 1Наприклад, ми створюємо робота-боксера. Для нас важливо, щоб він добре рухався, проводив точні удари, а також стежив за ворогом у пошуках слабких місць. Буде незручно писати все це в одному методі main , чи не так? Якщо ми опишемо все в одному методі, буде щось на зразок такого:
метод main() {
// Описание действий шага вперед
подача напряжения в отдельные модули;
поднятие ноги;
перевод в другую точку;
поставить ногу;
перенести вес на другую ногу;
если (противникАтакует()) {
        	// Описание действий уклонения робота.
        	...
} еслиНет {
        	// Описание действий обманного атакующего удара.
        	...
}
// Описание действий шага назад
...
}
А якщо нам знадобиться використовувати крок уперед чи удар ще десь у програмі? Чи описувати всі дії знову? Не підходить. Занадто багато рядків, що повторюються, в яких легко заплутатися. Нам потрібно винести опис деталей дії окремий модуль, який виконуватиме крок робота. І ми можемо викликати метод одним рядком. Якось так:
метод шагВперед() {
// Описание действий шага вперед
  	подача напряжения в отдельные модули;
  	поднятие ноги;
  	перевод в другую точку;
  	поставить ногу;
  	перенести вес на другую ногу;
}

метод уклонение() {
  	// Действия для уклонения
  	...
}

метод обманныйАтакующийУдар() {
  	// Действия для удара
  	...
}

метод шагНазад() {
  	// Действия для шага назад
  	...
}

метод противникАтакует() {
	// Робот проверяет атакует ли противник
}

метод main() {
	шагВперед();
	если (противникАтакует()) {
        	уклонение();
	} еслиНет {
  	  обманныйАтакующийУдар();
	}
	шагНазад();
}
Тепер ми маємо розділений функціонал робота, а також компактний і зрозумілий метод main() . Інші методи також можна розділити на будь-який функціонал, наприклад, обманний атакуючий удар можна розділити на методи обманного руху , руху, ніг , атаки . І їх, у свою чергу, на простіші завдання, щоб у результаті отримати набір елементарних. Окей, а тепер напишемо все це красиво в такому вигляді, який прийме Java.
public static void stepForward() {
  	    // Многострочный код, описывающий
  	    // действия робота для выполнения шага
  	    System.out.println("The robot takes a step forward");
}

public static void evasion() {
  	    // Действия для уклонения
  	    System.out.println("Robot shy of impact");
}

public static void deceptiveAttackBlow() {
  	    // Действия для удара
  	    System.out.println("The robot performs a deceptive strike");
}

public static void stepBack() {
  	    // Действия для шага назад
  	    System.out.println("The robot takes a step backwards");
}

public static void main(String[] args) {
    	stepForward();
    	if (isEnemyAttacked()) {
        		evasion();
    	} else {
  	    	deceptiveAttackBlow();
    	}
    	stepBack();
}

public static boolean isEnemyAttacked() {
    	// Метод проверяет, атакует ли враг. Повертає логическое значення.
    	return true;
}
Розумію, що вам може бути зараз цей код трохи незрозумілий, особливо деякі слова на зразок void , return і таке інше. Не поспішайте кидатися помідорами, зараз все поясню. Загальна думка парадигми "Поділяй і володарюй" вам має бути зрозумілою. У цьому нам допоможуть методи. Загальна структура оголошення методів така:
модификатор_доступа возвращаемое_значення ім'я_метода(принимаемые_параметры) {
   	//Тело метода
}

Модифікатор доступу

Модифікатор доступу – це кілька ключових слів: public , private , package . Ці слова вказують на область видимості методу. Я поясню просто: цим словом ви ніби ділитеся з іншими смакотою. Смакота - ваш метод. Якщо це private , ви не ділитеся методом з іншими класами. Якщо package ви ділитеся тільки з класами в рамках пакету (класи збираються в певні пакети, це ви дізнаєтеся далі). Ну а public показує, що ви - сама доброта і ділитеся смакотою (методом) з усією програмою. Якось так. Через кілька рівнів ви набагато краще зрозумієте роль цих слів.

Значення, що повертається

Подивіться приклад вище: всі методи позначені ключовим словом void , крім одного - isEnemyAttacked , який повертає логічне значення boolean . Якщо метод позначений як void , він може нічого не повертати. Такий метод просто виконує набір дій та все. А тепер зверніть увагу на метод main . Ті методи, які повертають void , викликаються просто так, у тілі методу. А ось метод isEnemyAttacked викликається в дужках оператора if. Завдяки тому, що він повертає логічне значення ми отримуємо можливість не використовувати проміжну змінну, а вставляти його безпосередньо. Повернення значення відбувається за допомогою ключового слова return . Якщо метод повертає тип int ми можемо викликати метод з будь-якого виразу:
public static int getNumber() {
 	    return 5;
}

public static void main(String[] args) {
    	int result = 5 + 6 + getNumber();
    	System.out.println(result);
}
Висновок:
16
Метод getNumber повертає значення типу int тому ми можемо викликати його з виразу. Також метод може повертати будь-який тип, включаючи ті, що ви створабо самі. Якщо ви вказали тип значення, що повертається у методу, то ви повинні повернути що-небудь. Не можна написати так:
public static int findMaxNumber(int a, int b) {
 	if(a>b) {
 	    return a;
 	}
}
Компілятор лаятиме вас, що при виконанні першої умови ви щось повертаєте, а при виконанні другої — ні.

Передача параметрів

У метод можна передавати параметри, що використовуються під час його роботи. Найпримітивніший приклад — підсумовування двох чисел. Але ж ми не примітивні, вірно? Візьмемо інший приклад, досить стереотипний. Припустимо, ми маємо метод chef() — кухар. Ми можемо передати в блоці параметрів цей метод інгредієнти супу, і в результаті цей метод повертає нам суп. Ось так:
public static void main(String[] args) {
    	String[] ingredients;
    	// Инициализация массива ингредиентов
    	Soup soup = chef(ingredients);

}

public static Soup chef(String[] ingredients) {
    	Soup soup = new Soup();
    	// Процесс варки супа
    	return soup;
}
(Припустимо, у нас є заздалегідь створений клас Soup ) У головному методі ми створюємо масив інгредієнтів, а потім "віддаємо його кухареві" (передаємо в метод chef ). "Кухар варить суп", а потім повертає його нам у вигляді об'єкта класу Soup . Все дуже просто. У метод можна передавати будь-які параметри, примітивні типи, об'єкти, масиви тощо.

Передача параметрів за посиланням та за значенням

У мові програмування Java будь-які параметри передаються методом за своїм значенням. Однак для примітивних типів і об'єктів цей механізм різний. Якщо ви передасте в метод будь-який примітивний тип і зміните його, він не зміниться в основному методі. Ви просто віддали копію значення, а оригінальна змінна збереглася. Найпростіший приклад:
public static void main(String[] args) {
    	int x = 1;
    	System.out.println(x);
    	getNumber(x);
    	System.out.println(x);

	}

	public static void getNumber(int i) {
    	i = i + 100;
	}
Висновок:
1 1
Однак у випадку з об'єктами зміни зачіпають оригінальний об'єкт:
public class Program
{
	public static void main(String[] args) {
    	WiseMan wiseMan = new WiseMan();
    	wiseMan.setIq(300);
    	System.out.println(wiseMan);
    	changeObject(wiseMan);
    	System.out.println(wiseMan);

	}

	public static void changeObject(WiseMan m) {
    	m.setIq(100);
	}
}

public class WiseMan {
	int iq;

	public void setIq(int iq) {
    	this.iq = iq;
	}

	public int getIq() {
    	return iq;
	}

	public String toString() {
    	return "Our wise man has an IQ "+iq;
	}
}
Висновок:
Ваша людина має IR 300 Ваша людина має IR 100
У нас є клас WiseMan (Мудрець), який має властивість iq . І два методи, які керують значенням цього поля. У головному методі ми створюємо об'єкт wiseMan , встановлюємо значення iq 300 . Потім ми передаємо метод changeObject нашого мудреця з iq 300. Але в цьому методі він дурнішає. Ми встановлюємо значення iq , що дорівнює 100. Потім у головному методі виводимо об'єкт. Видно, що в методі changeObject ми маніпулюємо іншим мудрецем у змінній m . Однак, ми змінюємо наш початковий об'єкт. Справа в тому, що об'єкт wiseMan в головному методі і об'єкт m , в методіchangeObject — той самий мудрець, а метод як параметр копіюється посилання об'єкт. Пам'ятайте про це, коли редагуватимете об'єкт в окремих методах.

Насамкінець кілька слів про модифікатора static

Взагалі кількома словами тут не обійтися, але я спробую. Звичайні методи, не позначені цим модифікатором, належать класу об'єкту. А static -методи належать самому класу. Прості методи можна використовувати в окремих об'єктів. Подивіться клас WiseMan з прикладу вище. Методи getIq та setIq у кожного мудреця будуть свої, адже рівень айкью у всіх різний. Якщо ми додамо в цей клас static метод generateAWisePhrase , то такий метод ми зможемо викликати без об'єкта:
WiseMan.generateAWisePhrase();
Загалом, цієї інформації поки що достатньо, адже про static можна написати кілька лекцій. Дотримуйтесь кількох правил під час написання методу для підтримання порядку у своєму коді:
  • Придумуйте своїм методам назви, що говорять, щоб було ясно, що вони роблять.
  • Намагайтеся не писати дуже довгих методів. Оптимальна довжина - 8-15 рядків.
  • Кількість параметрів методу має перевищувати 4-5.
  • Якщо у вашому коді двічі зустрічається схожий функціонал, подумайте: може варто узагальнити, винести його в окремий метод?
Ці способи допоможуть вам підвищити продуктивність вашої програми і, найголовніше, зроблять ваш код читальнішим.
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ