13 - Mantošana
Iemācies veidot klases hirearhijas un atkārtoti izmantot kodu efektīvi.
Mantošana ļauj izveidot jaunas klases balstoties uz pastāvošajām. Jaunā klase mantos visas īpašības un metodes no vecāku klases un var pievienot savas, vai modificēt mantotās.
Kas ir Mantojums?
Iedomājies to kā ģimenes koku. Bērns, kas no vecākiem mantojis īpašības, bet var arī radīt pats savas unikālās īpašības.
// Vecāku klase (superklase)
public class Entity {
protected String name;
protected int health;
public Entity(String name, int health) {
this.name = name;
this.health = health;
}
public void takeDamage(int damage) {
health -= damage;
System.out.println(name + " zaudēja " + damage + " dzīvības!");
}
}
// Bērna klase (subklase)
public class Player extends Entity {
private int level;
public Player(String name, int health, int level) {
super(name, health); // Izsauc vecāka konstruktoru
this.level = level;
}
public void levelUp() {
level++;
System.out.println(name + " pacēlās uz " + level + " līmeni!");
}
}- Superclass/Parent: Klase no kuras tiek mantots (Entity)
- Subclass/Child: Klase, kas manto (Player)
- extends: Atslēgvārds, lai mantotu no klases
- super: Atslēgvārds, kas piekļūst vecāka klases locekļiem
public class Monster extends Entity {
// Monstrs IR Entity
// Monstrs manto no Entity
// Entity ir vecāks, Monstrs ir bērns
}Extends atslēgvārds
Izmanto extends mantojot no klases:
public class Animal {
protected String name;
public void makeSound() {
System.out.println(name + " izdveš skaņu");
}
}
public class Dog extends Animal {
public void wagTail() {
System.out.println(name + " kustina asti");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.name = "Draudziņš";
dog.makeSound(); // Manto no Animal
dog.wagTail(); // Dog paša metode
}
}Super atslēgvārds
super atsaucās uz vecāku klasi:
Izsauc Vecāku Konstruktoru
public class Entity {
protected String name;
public Entity(String name) {
this.name = name;
}
}
public class Player extends Entity {
private int level;
public Player(String name, int level) {
super(name); // Izsauc vecāku konstruktoru VISPIRMS
this.level = level;
}
}super()jābūt pirmajam nosacījumam bērna konstruktorā- Ja neizsauksi
super(), Java automātiski izsauks bez-argumentu vecāku konstruktoru - Ja vecākam nav bez-argumentu konstruktora, tev OBLIGĀTI jāizsauc
super()ar argumentiem
// Nepareizi - super() nav vispirms
public Player(String name, int level) {
this.level = level;
super(name); // Kļūda!
}
// Pareizi
public Player(String name, int level) {
super(name); // Izsaukts pirmais
this.level = level;
}Vecāku Metodes Izsaukšana
public class Entity {
protected int health;
public void takeDamage(int damage) {
health -= damage;
System.out.println("Vienība tika ievainota!");
}
}
public class Player extends Entity {
@Override
public void takeDamage(int damage) {
super.takeDamage(damage); // Izsauc vecāku versiju
if (health < 20) {
System.out.println("Uzmanību: Maz Dzīvību!");
}
}
}Metodes Pārrakstīšana
Bērnu klases var būt aizvietotas ar vecāku metodēm:
public class Entity {
public void attack() {
System.out.println("Vienība uzbrūk!");
}
}
public class Player extends Entity {
@Override // Laba prakse izmantot šo anotāciju
public void attack() {
System.out.println("Spēlētājs vicina zobenu!");
}
}
public class Monster extends Entity {
@Override
public void attack() {
System.out.println("Monstrs iekož!");
}
}
public class Main {
public static void main(String[] args) {
Player player = new Player();
Monster monster = new Monster();
player.attack(); // "Spēlētājs vicina zobenu!"
monster.attack(); // "Monstrs iekož!"
}
}Vienmēr izmanto @Override, kad pārraksti metodes:
- Palīdz noķert drukas kļūdas (ja metode neeksistē vecākā, pretīm izmetīs kļūdu)
- Padara kodu tīrāku
- Laba dokumentācija
// Bez @Override - drukas kļūda netiek noķerta
public void attac() { // Drukas kļūda! Izveidos jaunu metodi
// ...
}
// Ar @Override - noķers kļūdu uzreiz
@Override
public void attac() { // Kļūda: metode neeksistē vecākā
// ...
}Pieejas Modifikātori iekš Mantojuma
public- Pieejams visurprotected- Pieejams klasēs un apakšklasēsprivate- Tikai klasē (netiek mantots)
public class Parent {
public int publicVar; // Bērns piekļūst
protected int protectedVar; // Bērns piekļūst
private int privateVar; // Bērns nepiekļūst
private void privateMethod() {
// Bērns nevar izsaukt
}
protected void protectedMethod() {
// Bērns var izsaukt
}
}
public class Child extends Parent {
public void test() {
publicVar = 10; // OK
protectedVar = 20; // OK
privateVar = 30; // Error!
protectedMethod(); // OK
privateMethod(); // Error!
}
}Praktiski Piemēri
Spēles Vienību Hierarhija
// Bāzes klase visām vienībām
public class Entity {
protected String name;
protected int health;
protected int maxHealth;
protected double x, y, z;
public Entity(String name, int maxHealth) {
this.name = name;
this.health = maxHealth;
this.maxHealth = maxHealth;
}
public void takeDamage(int damage) {
health -= damage;
if (health < 0) health = 0;
System.out.println(name + " took " + damage + " damage. Health: " + health);
}
public boolean isAlive() {
return health > 0;
}
public void moveTo(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
System.out.println(name + " moved to (" + x + ", " + y + ", " + z + ")");
}
}
// Spēlētājs paplašina vienību
public class Player extends Entity {
private int level;
private int experience;
private int mana;
public Player(String name) {
super(name, 100);
this.level = 1;
this.experience = 0;
this.mana = 50;
}
public void gainExperience(int amount) {
experience += amount;
System.out.println("Gained " + amount + " XP");
if (experience >= level * 100) {
levelUp();
}
}
private void levelUp() {
level++;
maxHealth += 10;
health = maxHealth;
mana += 5;
System.out.println("Level up! Now level " + level);
}
@Override
public void takeDamage(int damage) {
super.takeDamage(damage);
if (health < maxHealth * 0.25) {
System.out.println("⚠ WARNING: Low health!");
}
}
}
// Monstrs paplašina vienību
public class Monster extends Entity {
private int attackPower;
private String type;
public Monster(String name, int health, int attackPower, String type) {
super(name, health);
this.attackPower = attackPower;
this.type = type;
}
public int attack() {
System.out.println(name + " attacks!");
return attackPower;
}
@Override
public void takeDamage(int damage) {
super.takeDamage(damage);
if (!isAlive()) {
System.out.println(name + " was defeated!");
}
}
}
// Boss paplašina Monstru (multi-līmeņu mantojums)
public class Boss extends Monster {
private int phase;
public Boss(String name, int health, int attackPower) {
super(name, health, attackPower, "Boss");
this.phase = 1;
}
@Override
public void takeDamage(int damage) {
super.takeDamage(damage);
// Change phase at 50% health
if (phase == 1 && health < maxHealth / 2) {
phase = 2;
System.out.println(name + " enters PHASE 2!");
}
}
@Override
public int attack() {
int damage = super.attack();
if (phase == 2) {
damage *= 2;
System.out.println("ENRAGED ATTACK!");
}
return damage;
}
}Priekšmetu Hirearhija
// Bāzes Priekšmeta klase
public class Item {
protected String name;
protected int value;
protected double weight;
public Item(String name, int value, double weight) {
this.name = name;
this.value = value;
this.weight = weight;
}
public void use() {
System.out.println("Using " + name);
}
public String getInfo() {
return name + " ($" + value + ", " + weight + " kg)";
}
}
// Zobeni paplašina klasi
public class Weapon extends Item {
private int damage;
private int durability;
public Weapon(String name, int value, double weight, int damage, int durability) {
super(name, value, weight);
this.damage = damage;
this.durability = durability;
}
@Override
public void use() {
if (durability > 0) {
System.out.println("Attacking with " + name + " for " + damage + " damage!");
durability--;
} else {
System.out.println(name + " is broken!");
}
}
@Override
public String getInfo() {
return super.getInfo() + ", Damage: " + damage + ", Durability: " + durability;
}
}
// Lietojami priekšmeti paplašina priekšmetu
public class Consumable extends Item {
private int healAmount;
private int uses;
public Consumable(String name, int value, double weight, int healAmount, int uses) {
super(name, value, weight);
this.healAmount = healAmount;
this.uses = uses;
}
@Override
public void use() {
if (uses > 0) {
System.out.println("Used " + name + ", restored " + healAmount + " health!");
uses--;
} else {
System.out.println("No " + name + " left!");
}
}
@Override
public String getInfo() {
return super.getInfo() + ", Heals: " + healAmount + ", Uses: " + uses;
}
}
// Bruņas paplašina priekšmetu
public class Armor extends Item {
private int defense;
private String slot;
public Armor(String name, int value, double weight, int defense, String slot) {
super(name, value, weight);
this.defense = defense;
this.slot = slot;
}
@Override
public void use() {
System.out.println("Equipped " + name + " (+" + defense + " defense)");
}
@Override
public String getInfo() {
return super.getInfo() + ", Defense: " + defense + ", Slot: " + slot;
}
}Polimorfisms
Bērnu objekti var būt apstrādāti kā vecāku objekti:
Entity entity1 = new Player("Alice");
Entity entity2 = new Monster("Goblin", 50, 10, "Hostile");
Entity entity3 = new Boss("Dragon", 500, 50);
// Viss var izmantot Entity metodes
entity1.takeDamage(10);
entity2.takeDamage(10);
entity3.takeDamage(10);
// Masīvs dažādiem tipiem
Entity[] entities = {
new Player("Bob"),
new Monster("Zombie", 30, 8, "Hostile"),
new Monster("Spider", 20, 5, "Hostile")
};
// Apstrādā visas vienības vienādi
for (Entity entity : entities) {
entity.takeDamage(5);
}Polimorfisms ļauj rakstīt kodu, kas strādā ar vecāku tipiem, bet apstrādā bērnu tipus korekti:
public void damageEntity(Entity entity, int damage) {
entity.takeDamage(damage);
// Darbojas priekš Spēlētāja, Monstra, Bosa u.c.
// Katrs izmanto savu takeDamage() versiju
}
// Var izsaukt ar jebkuru vienības tipu
damageEntity(new Player("Alice"), 10);
damageEntity(new Monster("Goblin", 50, 10, "Hostile"), 10);
damageEntity(new Boss("Dragon", 500, 50), 10);Objekta Klase
Visas klases Javā automātiski manto no Object:
public class MyClass {
// Automātiski paplašina Object
// Jau pieejamas metodes kā toString(), equals(), u.tml.
}Biežākās Objektu metodes, ko pārraksta:
public class Player {
private String name;
private int level;
@Override
public String toString() {
return "Player: " + name + " (Lv. " + level + ")";
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Player) {
Player other = (Player) obj;
return this.name.equals(other.name);
}
return false;
}
}Fināla Klases un Metodes
final neļauj mantot, via pārrakstīt:
// Fināla klase - nevar paplašināt
public final class SpecialItem {
// No class can extend this
}
// Fināla metode - nevar pārrakstīt
public class Entity {
public final void printName() {
System.out.println(name);
}
}
public class Player extends Entity {
@Override
public void printName() { // Kļūda! Metode ir fināla
// Nevar pārrakstīt
}
}Biežākās Kļūdas
// Nepareizi - Aizmirsts super()
public class Player extends Entity {
public Player(String name) {
// Kļūda! Vienībai nav bez-argumentu konstruktora
}
}
// Pareizi
public class Player extends Entity {
public Player(String name) {
super(name, 100); // Izsauc vecāku konstruktoru
}
}
// Nepareizi - Piekļūst privātiem lietotājiem
public class Child extends Parent {
public void test() {
privateVar = 10; // Kļūda! private nav mantots
}
}
// Pareizi - Izmantojot protected
public class Parent {
protected int protectedVar; // Bērns var piekļūt
}
// Nepareizi - Vairuma Mantošana (nav atļauta Javā)
public class Child extends Parent1, Parent2 { // Kļūda!
}
// Pareizi - Tikai viena mantošanas klase
public class Child extends Parent {
}Prakses Vingrinājumi
-
Transportlīdzekļu hierarhija: Izveido "
Vehicleklasi ar tādām īpašībām kā ātrums un degviela. IzveidoCarunMotorcycleapakšklases ar tām unikālām īpašībām. -
Formu kalkulators: Izveido
Shapeklasi ar "calculateArea()" metodi. IzveidoCircle,Rectangle, unTriangleapakšklases, kas pārraksta šo metodi. -
Lomu Spēles Tēli: Izveido
Characterklasi. Paplašini to arWarrior,Mage, unArcherklasēm, katrai ar unikālām spējām. -
Dzīvnieku skaņas: Izveido
Animalklasi armakeSound()metodi. Izveido vairākas dzīvnieku apakšklases, kas pārraksta šo metodi.