07 - Вступ до об'єктно-орієнтованого програмування
Вивчіть основи класів та об'єктів у Java.
Об'єктно-орієнтоване програмування (ООП) є основою Java та модифікацій Hytale. Замість того, щоб просто мати змінні та методи, ми організовуємо їх у класи та об'єкти.
Що таке клас?
Клас - це план для створення об'єктів. Уявіть його як рецепт або шаблон.
public class Player {
// Властивості (дані)
String name;
int health;
int level;
// Поведінка (методи)
public void takeDamage(int damage) {
health -= damage;
System.out.println(name + " отримав(-ла) " + damage + " шкоди!");
}
}Що таке об'єкт?
Об'єкт - це екземпляр, створений на основі класу. Якщо клас - це креслення, то об'єкт - це реальна річ, побудована за цим кресленням.
public class Main {
public static void main(String[] args) {
// Створити об'єкти з класу Player
Player player1 = new Player();
player1.name = "Анна";
player1.health = 100;
player1.level = 5;
Player player2 = new Player();
player2.name = "Богдан";
player2.health = 80;
player2.level = 3;
// Використання об'єктів
player1.takeDamage(20); // Анна отримав(-ла) 20 шкоди!
player2.takeDamage(15); // Богдан отримав(-ла) 15 шкоди!
}
}Клас = креслення (ідея гравця) Об'єкт = реальна річ (Анна, Богдан, конкретні гравці)
Один клас може створити багато об'єктів, так само як один рецепт може створити багато тортів!
Створення простого класу
Створімо клас Sword для Hytale:
public class Sword {
// Властивості
String name;
int damage;
int durability;
// Метод використання меча
public void attack(String target) {
System.out.println("Атакує " + target + " на " + damage + " шкоди!");
durability -= 1;
if (durability <= 0) {
System.out.println(name + " зламався!");
}
}
// Метод для відображення інформації
public void displayInfo() {
System.out.println("Зброя: " + name);
System.out.println("Шкода: " + damage);
System.out.println("Міцність: " + durability);
}
}Використання класу:
public class Main {
public static void main(String[] args) {
Sword sword = new Sword();
sword.name = "Залізний меч";
sword.damage = 15;
sword.durability = 3;
sword.displayInfo();
sword.attack("Зомбі");
sword.attack("Скелет");
sword.attack("Павук"); // Це зламає меч
}
}Конструктори
Замість того, щоб встановлювати властивості по одній, використовуйте конструктор для ініціалізації об'єктів:
public class Sword {
String name;
int damage;
int durability;
// Конструктор
public Sword(String weaponName, int weaponDamage, int weaponDurability) {
name = weaponName;
damage = weaponDamage;
durability = weaponDurability;
}
public void attack(String target) {
System.out.println("Атакує " + target + " на " + damage + " шкоди!");
durability--;
}
}Тепер створювати мечі стало простіше:
public class Main {
public static void main(String[] args) {
// Набагато простіше!
Sword ironSword = new Sword("Залізний меч", 15, 100);
Sword diamondSword = new Sword("Діамантовий меч", 25, 200);
ironSword.attack("Зомбі");
diamondSword.attack("Бос");
}
}- Така сама назва, як і клас
- Без типу повернення (навіть
void) - Викликається автоматично при використанні
new - Може мати кілька конструкторів (перевантаження)
public class Item {
String name;
int value;
// Конструктор з усіма параметрами
public Item(String name, int value) {
this.name = name;
this.value = value;
}
// Конструктор тільки з ім'ям
public Item(String name) {
this.name = name;
this.value = 0; // Значення за замовчуванням
}
}Ключове слово this
this посилається на поточний об'єкт. Використовуйте його для уточнення, коли імена параметрів збігаються з іменами властивостей:
public class Player {
String name;
int health;
public Player(String name, int health) {
this.name = name; // this.name = властивість
this.health = health; // name = параметр
}
}Без this Java заплутується:
public Player(String name, int health) {
name = name; // ❌ Чиє ім'я? Неоднозначно!
health = health; // ❌ Чиє здоров'я? Неоднозначно!
}Практичні приклади
Клас предмету
public class Item {
String name;
String type;
int quantity;
double weight;
public Item(String name, String type, int quantity, double weight) {
this.name = name;
this.type = type;
this.quantity = quantity;
this.weight = weight;
}
public void use() {
if (quantity > 0) {
quantity--;
System.out.println("Використано " + name + ". Залишилося: " + quantity);
} else {
System.out.println("Більше " + name + " не лишилось!");
}
}
public double getTotalWeight() {
return weight * quantity;
}
}public class Main {
public static void main(String[] args) {
Item potion = new Item("Зілля здоров'я", "Витратний", 5, 0.5);
potion.use(); // Використано Зілля здоров'я. Залишилося: 4
System.out.println("Загальна вага: " + potion.getTotalWeight()); // 2.0
}
}Клас монстра
public class Monster {
String name;
int health;
int attack;
boolean isHostile;
public Monster(String name, int health, int attack, boolean isHostile) {
this.name = name;
this.health = health;
this.attack = attack;
this.isHostile = isHostile;
}
public void takeDamage(int damage) {
health -= damage;
System.out.println(name + " отримав(-ла) " + damage + " шкоди!");
if (health <= 0) {
System.out.println(name + " був переможений!");
} else {
System.out.println(name + " має ще " + health + " здоров'я.");
}
}
public int attackPlayer() {
if (isHostile && health > 0) {
System.out.println(name + " атакує на " + attack + " шкоди!");
return attack;
}
return 0;
}
public boolean isAlive() {
return health > 0;
}
}public class Main {
public static void main(String[] args) {
Monster zombie = new Monster("Зомбі", 50, 10, true);
Monster chicken = new Monster("Курка", 10, 0, false);
zombie.takeDamage(20); // Зомбі отримав(-ла) 20 шкоди!
int damage = zombie.attackPlayer(); // Зомбі атакує на 10 шкоди!
if (zombie.isAlive()) {
System.out.println("Монстр досі живий!");
}
}
}Клас блоку
public class Block {
String type;
int x, y, z;
boolean isSolid;
int hardness;
public Block(String type, int x, int y, int z, boolean isSolid, int hardness) {
this.type = type;
this.x = x;
this.y = y;
this.z = z;
this.isSolid = isSolid;
this.hardness = hardness;
}
public void breakBlock() {
System.out.println("Ламає " + type + " блок в (" + x + ", " + y + ", " + z + ")");
System.out.println("Твердість: " + hardness);
}
public String getPosition() {
return "(" + x + ", " + y + ", " + z + ")";
}
public boolean canWalkThrough() {
return !isSolid;
}
}Модифікатори доступу (попередній перегляд)
Ви вже бачили public - це означає "доступний для всіх". Пізніше ми дізнаємося більше про контроль доступу, а поки що ось попередній перегляд:
public class Example {
public String publicVar; // Доступний для всіх
private String privateVar; // Доступний тільки для цього класу
/* (без модифікатора) */ String defaultVar; // Доступ до пакета
}Наразі використовуйте public для всього. Коли використовувати private, ми дізнаємося в наступній статті.
Класи допомагають:
- Організувати пов'язані дані та методи разом
- Легко повторно використовувати код (створювати багато об'єктів з одного класу)
- Моделювати реальні речі (гравців, предмети, монстрів)
- Підтримувати код (зміни в одному місці впливають на всі об'єкти)
Без класів для управління 100 гравцями знадобилося б 100 окремих змінних для кожної властивості. З класами це лише 100 об'єктів гравця!
Практичні вправи
-
Створіть клас
Potion:- Властивості: name, healAmount, uses
- Конструктор для встановлення всіх властивостей
- Метод
drink(), який лікує і зменшує використання (uses) - Метод
isEmpty(), який повертає true, якщо використання (uses) менше або дорівнює 0
-
Створіть клас
Chest:- Властивості: isLocked, itemCount, capacity
- Конструктор
- Метод
addItem(), який перевіряє capacity - Метод
unlock(), який встановлює isLocked на false - Метод
isFull(), який перевіряє, чи itemCount >= capacity
-
Створіть клас
Villager:- Властивості: name, profession, tradeCount
- Конструктор
- Метод
greet(), який виводить привітання - Метод
trade(), який збільшує tradeCount - Метод
getInfo(), який відображає всі властивості
-
Створіть кілька об'єктів: Використовуючи будь-який створений вами клас, створіть 3 різних об'єкти та протестуйте всі їхні методи.