Abstract Classes
Uneori vrei o clasă care este un șablon: definește ce TREBUIE să facă clasele copil, dar nu poate fi folosită singură. Asta este o clasă abstractă
Gândește-te așa: „Vehicul" este un concept. Nu poți construi pur și simplu un „vehicul" generic. Construiești o mașină sport, o motocicletă, un camion. Dar toate împărtășesc ideea de a fi un vehicul. În Java, ai face Vehicul abstract
abstract class Vehicul {
String nume;
Vehicul(String nume) {
this.nume = nume;
}
abstract int vitezaMaxima(); // fara corp! copiii TREBUIE sa implementeze asta
void claxon() {
System.out.println(nume + " face BIP!");
}
}
Două lucruri cheie aici:
- Clasa este marcată
abstract, deci NU poți facenew Vehicul("ceva") - Metoda
vitezaMaxima()este marcatăabstract: NU are corp (fără acolade), doar un punct și virgulă. Orice copil ne-abstract TREBUIE să furnizeze corpul
public class Main {
public static void main(String[] args) {
Vehicul v = new Vehicul("test"); // EROARE DE COMPILARE! Nu poti instantia o clasa abstracta
}
}
Este ca și cum ai încerca să cumperi un „vehicul" de la un dealer. Vânzătorul ar spune „ce FEL de vehicul?" Ai nevoie de un tip concret
O clasă copil care extinde o clasă abstractă TREBUIE să implementeze toate metodele abstracte, sau trebuie să fie ea însăși abstractă
abstract class Vehicul {
String nume;
Vehicul(String nume) { this.nume = nume; }
abstract int vitezaMaxima();
}
class Sportiva extends Vehicul {
Sportiva(String nume) {
super(nume);
}
@Override
int vitezaMaxima() {
return 240;
}
}
class Motocicleta extends Vehicul {
Motocicleta(String nume) {
super(nume);
}
@Override
int vitezaMaxima() {
return 200;
}
}
public class Main {
public static void main(String[] args) {
Sportiva infernus = new Sportiva("Infernus");
Motocicleta angel = new Motocicleta("Angel");
System.out.println(infernus.nume + ": " + infernus.vitezaMaxima() + " km/h");
System.out.println(angel.nume + ": " + angel.vitezaMaxima() + " km/h");
}
}
Ieșire
Infernus: 240 km/h
Angel: 200 km/h
O clasă abstractă poate avea atât metode abstracte (pe care copiii trebuie să le implementeze) cât și metode obișnuite (pe care copiii le moștenesc gratuit)
abstract class Personaj {
String nume;
int viata;
Personaj(String nume, int viata) {
this.nume = nume;
this.viata = viata;
}
// Abstract - fiecare personaj lupta diferit
abstract void ataca();
// Concret - toate personajele primesc daune la fel
void primesteDaune(int cantitate) {
viata -= cantitate;
System.out.println(nume + " primeste " + cantitate + " daune! HP: " + viata);
}
}
Tommy Vercetti și Lance Vance ar extinde amândoi Personaj. Fiecare ar avea propriul stil de ataca(), dar primesteDaune() funcționează la fel pentru toți
Când folosești o clasă abstractă vs o clasă obișnuită?
Folosește o clasă obișnuită când are sens să creezi obiecte de acel tip direct. O Masina este un lucru real, poți crea una
Folosește o clasă abstractă când clasa este doar un concept sau o categorie. „Vehicul" este abstract: nu există așa ceva ca un vehicul generic. „Personaj" ar putea fi oricare dintre cele două, în funcție de designul tău
Regula de bază: dacă nu ai vrea niciodată ca cineva să scrie new ClasaTa(), fă-o abstractă
Misiune: Flota lui Tommy
Tommy are mai multe vehicule în garaj, fiecare cu viteza lui maximă. Are nevoie de un raport care arată fiecare vehicul și viteza lui, dar „Vehicul" în sine e doar un concept, nu ceva ce poți construi direct.
Creează o clasă abstractă Vehicul cu un câmp String nume, un constructor și o metodă abstractă vitezaMaxima() care returnează un int. Apoi creează două clase concrete:
Sportiva:vitezaMaxima()returnează240Motocicleta:vitezaMaxima()returnează200
În main, stochează cele două nume în variabilele nume1 și nume2 (pornește cu "Infernus" și "Angel"). Creează o Sportiva din nume1 și o Motocicleta din nume2. Afișează fiecare în formatul Nume: X km/h.
Exemplu
Infernus: 240 km/h
Angel: 200 km/h