Моддинг Hytale
Основы Java

07 - Введение в объектно-ориентированное программирование

Изучение основ классов и объектов в Java.

Object-Oriented Programming (OOP) - это основа Java и моддинга в Hytale. Вместо того чтобы использовать множество хаотично плавающих переменных и объектов мы организуем их в классы и объекты.

Что такое Класс?

Класс по сути своей чертёж для создания объекта. Думайте о нём, как о рецепте или шаблоне.

public class Player {
    // Свойства(данные, информация)
    String name;
    int health;
    int level;
    
    // Поведение (методы)
    public void takeDamage(int damage) {
        health -= damage;
        System.out.println(name + " took " + damage + " damage!");
    }
}

Что такое Объект?

Объект по сути своей реализация класса(чертежа). Если класс - чертеж, то объект - это по сути реализация класса, он построен на основе этого самого чертежа.

public class Main {
    public static void main(String[] args) {
        // Create objects from the Player class
        Player player1 = new Player();
        player1.name = "Alice";
        player1.health = 100;
        player1.level = 5;
        
        Player player2 = new Player();
        player2.name = "Bob";
        player2.health = 80;
        player2.level = 3;
        
        // Use the objects
        player1.takeDamage(20);  // Алиса получила 20 урона!
        player2.takeDamage(15);  // Боб получил 15 урона!
    }
}
Класс и Объект, в чём разница?

Class = Чертёж (идея игрока) Object = Существующий объект (Алиса, Боб, конкретный игрок)

Один класс может создать много объектов, так же как из одного рецепта можно приготовить много тортиков!

Создание простого класса

Для начала создадим класс Меч для Hytale:

public class Sword {
    // Характеристики
    String name;
    int damage ;
    int durability;
    
    // Метод для использования меча
    public void attack(String target) {
        System. ut.println(target + " получил " + damage + " урона!");
        durability -= 1;
        
        if (durability <= 0) {
            System. ut.println(name + " сломался! );
        }
    }
    
    // Метод отображения информации
    public void displayInfo() {
        System. ut.println("Оружие: " + name);
        Система. ut.println("Урон: " + damage);
        Система. ut.println("Прочность: " + durability);
    }
}

Пример класса:

public class Main {
    public static void main(String[] args) {
        Sword sword = new Sword();
        sword.name = "Iron Sword";
        sword.damage = 15;
        sword.durability = 3;
        
        sword.displayInfo();
        sword.attack("Zombie");
        sword.attack("Skeleton");
        sword.attack("Spider");  // Данная атака может сломать меч
    }
}

Конструкторы.

Вместо того чтобы устанавливать значения каждого свойства по одному, используйте конструктор для инициализации объектов:

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("Attacking " + target + " for " + damage + " damage!");
        durability--;
    }
}

Теперь создать меч стало проще:

public class Main {
    public static void main(String[] args) {
        // Much cleaner!
        Sword ironSword = new Sword("Iron Sword", 15, 100);
        Sword diamondSword = new Sword("Diamond Sword", 25, 200);
        
        ironSword.attack("Zombie");
        diamondSword.attack("Boss");
    }
}
Правила использование Конструкторов.
  • Имя должно соответствовать названию класса.
  • Нет возвращаемого типа (даже void)
  • Вызывается автоматически при использовании new
  • Можно использовать несколько конструкторов (перегрузка)
public class Item {
    String name;
    int value;
    
    // Конструктор со всеми параметрами
    public Item(String name, int value) {
        это. ame = name;
        это. alue = значение;
    }
    
    // Конструктор только с названием
    public Item(String name) {
        this. ame = name;
        это. alue = 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; // ❌ Чьё здоровье? Непонятно!
}

Практические примеры

Класс Item(Предмет)

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("Used " + name + ". Remaining: " + quantity);
        } else {
            System.out.println("No more " + name + " left!");
        }
    }
    
    public double getTotalWeight() {
        return weight * quantity;
    }
}
public class Main {
    public static void main(String[] args) {
        Item potion = new Item("Health Potion", "Consumable", 5, 0.5);
        
        potion.use();  // Использовал зелье регенерации. Осталось: 4
        System.out.println("Total weight: " + potion.getTotalWeight()); // 2.0
    }
}

Класс Monster(Монстр)

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 + " took " + damage + " damage!");
        
        if (health <= 0) {
            System.out.println(name + " was defeated!");
        } else {
            System.out.println(name + " has " + health + " health left.");
        }
    }
    
    public int attackPlayer() {
        if (isHostile && health > 0) {
            System.out.println(name + " attacks for " + attack + " damage!");
            return attack;
        }
        return 0;
    }
    
    public boolean isAlive() {
        return health > 0;
    }
}
public class Main {
    public static void main(String[] args) {
        Monster zombie = new Monster("Zombie", 50, 10, true);
        Monster chicken = new Monster("Chicken", 10, 0, false);
        
        zombie.takeDamage(20);        // Зомби получил 20 урона!
        int damage = zombie.attackPlayer();  // Зомби получил 10 урона!
        
        if (zombie.isAlive()) {
            System.out.println("Monster is still alive!");
        }
    }
}

Класс Block(Блок)

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("Breaking " + type + " block at (" + x + ", " + y + ", " + z + ")");
        System.out.println("Hardness: " + 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 игроков всего лишь объекты!

Практические Задания

  1. Создайте класс Potion:

    • Свойства: name, healAmount, uses
    • Конструктор для назначения всех указанных свойств
    • Метод drink() который хилит игрока и уменьшает количество предмета
    • Метод IsEmpty() который возвращает true если значение меньше или равно 0 (хотя количество предметов в большинстве случаев не должно опускать до отрицательных значений если это не предусмотрено вашим модом, игрой или проектом в целом)
  2. Создайте класс Chest:

    • Свойства: IsLocked, itemCount, capacity
    • Конструктор
    • Метод addItem() который проверяет вместимость сундука
    • Метод unlock() который меняет значение isLocked на false
    • Метод isFull() который проверяет условие itemCount >= capacity
  3. Создайте класс Vilagger

    • Свойства: name, profession, tradeCount
    • Коструктор
    • Метод greet(), который выведет приветствие
    • Метод trade() который будет увеличивать значение tradeCount
    • Метод getInfo(), который отображает все характеристики
  4. Создать несколько объектов: Используя любой созданный тобой класс, создай 3 разных объекта и протестируй все связанные с ними методы.