Існує один цікавий принцип, про який багато хто чув. Він називається "Поділяй і володарюй". Цей принцип використовується у багатьох сферах людського життя, наприклад, у політиці. Він означає поділ великої кількості різнорідних частин у державі, розпалювання та використання ворожнечі між цими частинами. Іншими словами: створити конфлікт між тими, хто потенційно створює загрозу владі. Але ми з вами програмісти, тому нас цікавить виключно технічне трактування цього принципу. А звучить вона так: “Принцип “Поділяй і владарюй” полягає у розбитті великого завдання на дрібніші доти, доки вони не стануть елементарними. Потім потрібно послідовно вирішити їх і поєднати все в одну цілу систему. Ця програма повинна вирішувати поставлене завдання” Тобто, ви просто розбиваєте велике завдання на дрібніші, вирішити які вам не становить проблем. А потім збираєте рішення в одне велике. Щоб дотримуватися цього простого і корисного принципу, Java-програмування використовують методи. Наприклад, ми створюємо робота-боксера. Для нас важливо, щоб він добре рухався, проводив точні удари, а також стежив за ворогом у пошуках слабких місць. Буде незручно писати все це в одному методі 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.
- Якщо у вашому коді двічі зустрічається схожий функціонал, подумайте: може варто узагальнити, винести його в окремий метод?
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ