You are on page 1of 20

ExceptionGameEnded

package xando;
@SuppressWarnings("serial")
public class ExceptionGameEnded extends Exception {
public boolean win;
public Point winningCell;
public ExceptionGameEnded(String message, boolean win, Point
winningCell) {
super(message);
this.win = win;
this.winningCell = winningCell;
}
}
Point
package xando;
public class Point {
public int row;
public int col;
public Point(int row, int column) {
this.row = row;
col = column;
}

// metoda folosita pentru a suprascrie metoda equals din clasa Object


@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + col;
result = prime * result + row;
return result;
}
// am extins pentru a putea verifica daca un nou Point este deja in setul de
pozitii goale si a il putea elimina, in caz ca voi ocupa pozitia
@Override
public boolean equals(Object obj) {

if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Point))
return false;
Point other = (Point) obj;
if (col != other.col)
return false;
if (row != other.row)
return false;
return true;
}
}
Player
package xando;
import
import
import
import

java.util.HashSet;
java.util.Iterator;
java.util.Random;
java.util.Set;

public class Player {


private char[][] board; // 0 pt celulele goale, X si O pentru cele ocupate de
cei 2 jucatori
private Set<Point> emptyCells; // reprezinta Set-ul de celule goale de pe
board
private int N; // nr de linii
private int M; // nr de coloane
private int winLength;
public Player(int nrOfRows, int nrOfColumns, int winLength) {
board = new char[nrOfRows][nrOfColumns];
this.winLength = winLength;
N = nrOfRows;
M = nrOfColumns;
emptyCells = new HashSet<Point>();
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
emptyCells.add(new Point(i, j));

}
}
}

// Daca pozitia punctului primit este buna si nu este ocupata se


pozitioneaza X pe tabla si este scoasa pozitia goala din Set si verifica daca
mutarea facuta este castigatoare
public void read(Point selectedCell) throws Exception {
if (!emptyCells.contains(selectedCell) || selectedCell.row >= N ||
selectedCell.col >= M) // celula ocupata
throw new Exception("Opponent choose a bad Position!!");
board[selectedCell.row][selectedCell.col] = 'X';
emptyCells.remove(selectedCell);
printBoard();
if (checkWin(selectedCell.row, selectedCell.col, 'X'))
throw new ExceptionGameEnded("Opponent won!!", false,
selectedCell);
}
// cheama "algoritmul" pentru a afla pozitia in care va plasa O dupa care
ocupa pozitia pe board si sterge pozitia goala din Set si verifica daca
mutarea facuta este castigatoare
public Point next() throws ExceptionGameEnded {
Point point = getRandomPosition();
board[point.row][point.col] = 'O';
emptyCells.remove(point);
printBoard();
if (checkWin(point.row, point.col, 'O'))
throw new ExceptionGameEnded("You won!!", true, point);
return point;
}
// reseteaza starea jocului aproape ca in constructor
public void reset() {
board = new char[N][M];

emptyCells = new HashSet<Point>();


for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
emptyCells.add(new Point(i, j));
}
}
}

// strategia folosita de mine este aceea de a lua o celula goala la


intamplare si a pune O pe ea
private Point getRandomPosition() {
int index = new Random().nextInt(emptyCells.size());
Iterator<Point> iter = emptyCells.iterator();
for (int i = 0; i < index; i++) {
iter.next();
}
return iter.next();
}
// metoda folosita in metodele ce modifica starea jocului
// dupa ce este ocupata o noua celula, se verifica daca unul din jucatori a
castigat, iar celalalt a pierdut sau a facut egal
private boolean checkWin(int row, int col, char XO) throws
ExceptionGameEnded {
// verific pe linie
int count = 0;
for (int i = 0; i < M; i++) {
if (board[row][i] != XO && count > 0)
break;
else if (board[row][i] == XO) {
count++;
if (count == winLength) {
return true;
}
}
}
// verific pe coloana
count = 0;
for (int i = 0; i < N; i++) {

if (board[i][col] != XO)
break;
else {
count++;
if (count == winLength) {
return true;
}
}
}

// verific pe diagonala
count = 0;
for (int i = 0, j = 0; i < N && j < M; i++, j++) {
if (board[i][j] != XO)
break;
else {
count++;
if (count == winLength) {
return true;
}
}
}
// verific pe diagonala secundara
count = 0;
for (int i = 0, j = 0; i < N && j < M; i++, j++) {
if (board[i][(M - 1) - j] != XO)
break;
else {
count++;
if (count == winLength) {
return true;
}
}
}
// verific daca mai sunt pozitii celule goale
// daca nu, atunci este egalitate deoarece nu a returnat true pana sa
ajunga aici
if (emptyCells.isEmpty())

throw new ExceptionGameEnded("Draw!!", false, new Point(-1, -1));


return false;
}
// metoda ce afiseaza jocul este folosita in fiecare metoda in care este
updatata starea jocului
private void printBoard() {
for (int row = 0; row < N; ++row) {
for (int col = 0; col < M; ++col) {
System.out.print(board[row][col]);
if (col != board[row].length - 1) {
System.out.print(" | ");
}
}
System.out.println();
if (row != N - 1) {
System.out.println("-----------");
}
}
System.out.println();
}
}

public static void main(String [] args){} se numeste metoda principala a


programlului. Orice aplicatie isi incepe executia de pe prima linie a metodei
principale.
Orice program lucreaza cu date, iar pentru a lucra cu date acestea
trebuiesc stocate. Deoarece memoria unui sistem in care putem stoca
informatie este limitata pentru a plasa o informatie in memorie este
necesar mai intai sa rezervam o zona in memorie in functie de tipul
informatiei care va fi stocata. O informatie poate fi stocata sub forma de
numar intreg, numar real, caracter, valoare booleana (adevarat sau fals)
sau instanta. In afara de ultimul tip enumerat mai devreme toate celelalte
informatii reprezinta tipuri de date primitive. In functie de cantitatea de
informatie (care depinde atat de tip cat si de valoarea pe care dorim sa o
stocam) se rezerva o zona de memorie mai mare sau mai mica in memoria
interna a sistemului. Mai jos am enumerat tipurile primitive pe care le
putem folosi in programarea cu Java:

short

int

long

float

double

byte

boolean

char

Orice zona de memorie se defineste folosind un tip de data si un nume


(sau identificator); Numele se poate alege dupa urmatoarele reguli:
1. nu poate incepe cu cifra
2. nu poate contine caractere speciale
3. nu poate fi cuvant rezervat (keyword)
Sintaxa pentru rezervarea unei zone de memorie este de forma <tip>
<identificator>;

Aceste zone de memorie reprezinta parti ale memoriei interne. Memoria


interna se imparte in doua zone: stack si heap. Datele primitive sunt
stocate in zone rezervate din stack;
Primitivele int, long, byte, short: reprezinta zone de memorie
rezervate pentru stocarea valorilor numerice intregi. Cel mai des, dintre
acestea este folosit tipul int;
Primitivele float si double: reprezinta zone de memorie folosite pentru
stocarea valorilor numerice reale. Diferenta dintre cele doua tipuri de
primitive este precizia zecimalelor valorilor stocate. Chiar daca float si
double sunt folosite pentru acelasi tip de date nu putem transporta
informatia dintr-un double intr-un float in mod direct, deoarece este posibila
pierderea de precizie a valorii cu care se face aceasta operatiune. Pentru a
pune totusi o valoare stocata intr-o zona de memorie double intr-un float
putem folosi conversia explicita. Acest lucru se poate face in felul urmator:
Primitiva char: poate fi folosita pentru a stoca caractere in format
Unicode.
Primitiva boolean: este folosita pentru a stoca una dintre
valorile true sau false; Spre deosebire de alte limbaje de programare nu
mai exista posibilitatea de a folosi valorile 1 si 0 pentru adevarat sau fals.
Pentru a reprezenta valorile adevarat sau fals (tip boolean) singura
modalitate este folosirea cuvintelor true si false. true si false se scriu
numai cu litere mici si reprezinta cuvinte rezervate in Java.
De obicei zonele de memorie pe care le folosim sunt variabile. Acest
lucru inseamna ca valoarea acelei zone de memorie se modifica pe
parcursul executiei programului. Exista totusi necesitatea uneori de zone de
memorie carora sa nu li se schimbe valoarea pe parcursul executiei
programului. Marcam aceste zone de memorie folosind un cuvant cheie cu
valaore de modificator: final;
Daca o zona de memorie la declarare este final atunci aceasta este
constanta si odata atribuita o valoare acestei zone de memoria, valoarea
atribuita nu mai poate fi modificata pe parcursul executiei programului.
Instructiunea folosita pana in acest moment pentru a afisa in consola un
mesaj a fost System.out.println(); Intre cele doua paranteze putem fie da ca
parametru un sir de caractere, fie un numar sau chiar o valoare boolean.
Instructiunea este suficient de complexa incat in acest moment nu poate fi
inteleasa in detaliu. Vom folosi pentru afisarea in consola doua instructiuni:

System.out.print()

System.out.println()

Diferenta intre cele doua este ca a doua concateneaza imediat dupa


parametrul dat pentru afisare caracterul unicode de linie noua \n. In felul
acesta ceea ce va fi afisat ulterior se va afla pe urmatoarea linie in consola.
Clase
In programarea orientata pe obiecte, spre deorebire de programarea
procedurala vom defini obiecte, le vom crea mai apoi (sau instantia) si
instantele create vor interactiona pentru a defini programul. Clasa are unul
dintre cele mai importante roluri. O clasa reprezinta o matrita (schita) care
defineste un prototip. Aceasta descrie modul in care vor arata instantele
create. Un obiect este definit de o clasa prin atribute si comportamente.
Atributele reprezinta ceea ce cunoaste obiectul, iar comportamentele ceea
ce stie obiectul sa faca.
Definirea unei clase se face cu ajutorul cuvantului cheie class:
Class
Nume{
}
Standard numele unei clase incepe cu litera capitala. Fiind identificator,
numele clasei se scrie si respecta aceleasi reguli ca in cazul scrierii numelor
de variabile.
Inaintea cuvantului cheie class se pot pune modificatori. Despre
modificatori vom discuta in acest curs in lectiile urmatoare.
public class Program{
}
Acoladele (in engleza braces) incadreaza blocul de cod al unei clase. In
clasa se pot defini si initializa zone de memorie, se pot defini metode si
chiar putem crea alte clase. Alte instructiuni nu pot fi facute direct intre
acoladele ce incadreaza blocul de cod al unei clase.
O clasa precedata la definitie de modificatorul de acces public trebuie
scrisa intr-un fisier care sa aiba numele acestei clase (va aminesc faptul ca
limbajul face diferenta intre litere mari si litere mici) si extensia .java; Intrun fisier cu extensia .java nu pot exista mai multe clase definite public.
Clase care nu sunt precedate de acest modificator pot fi puse mai multe in
acelas fisier .java; Un fisier cu extensia .java trebuie sa contina macar o
clasa publica;

Obiecte si definirea atributelor

Un obiect este definit de o clasa. Un program orientat pe obiecte se


foloseste de instante de obiecte si interactiuni intre acestea la executie.
Clasa defineste modul in care va arata si se va comporta un obiect; Prin
urmare obiectul are doua caracteristici importante: Atributele si
Comportamentul (in engleza attributes and behaviour);
Atributele pot fi zone de memorie primitive sau alte instante de obiecte;
Acesta este primul mod in care doua instante de obiecte pot interactiona
(De exemplu: obiectul masina are patru instante ale obiectului roata).
Comportamentul unui
metode de instanta;

obiect

este

reprezentat

de metode numite

Descrierea unui obiect prin atributele sale:


Standard atributele unui obiect sunt primele scrise in clasa; De exemplu
sa presupunem ca vrem sa programam o minge; Iata cateva atribute care
ar putea descrie acest obiect:

String culoare

double greutate

double presiuneInterna

Pentru a defini acest obiect trebuie sa construim clasa Minge care sa


contina aceste zone de memorie.
public
String
double
double

class Minge{
culoare;
greutate;
presiuneInterna;

}
Comportamente

Metodele reprezinta blocuri de instructiuni care sunt definite si pot fi


apelate ulterior de oricate ori este nevoie. Aceste blocuri de instructiuni
sunt identificate printr-un nume si pot primi informatii pentru executie
(numite parametrii sau argumente) avand si posibilitate de a oferi informatii

utile la finalizare (informatiile oferite la finalul executiei unei metode se


numeste date returnate).
Se numeste semnatura metodei tipul acesteia impreuna cu numele si
parametrii. Modificatorii nu sunt obligatorii in scrierea unei metode, insa
orice metoda trebuie sa aiba macar un tip, un nume si parantezele
parametrilor chiar daca nu primeste niciun parametru. Tipul metodei
reprezinta exact tipul informatiei pe care o returneaza. Daca metoda nu
returneaza nicio data atunci tipul acesteia este void.
Instructiunea return este responsabila de returnarea valorii. In cazul
acesta valoarea este suma celor doua numere date prin parametri.
Intotdeauna tipul datei returnate trebuie sa corespunda cu tipul metodei. In
exemplul de mai sus este definit corect, deoarece suma a doua numere
reale nu poate fi decat un numar tot real. Un aspect imporant este faptul ca
o metoda nu poate returna decat o vaoare. Odata apelata instructiunea
return metoda isi incheie activitatea. Chiar daca ar mai exista alte
instructiuni dupa return acestea nu ar fi executate.

Constructorul si crearea instantelor

Dupa ce am descris obiectul prin atributele si comportamentele sale este


timpul sa cream instante ale acestuia. Instantele reprezinta entitatile care
pot interactiona intre ele pentru a da un scop programului nostru. Daca in
interiorul clasei obiectul era descris prin atributele sale, diferenta
intre prototipul definit de clasa si o instanta construita cu ajutorul
acestuia este ca atributele nu mai sunt formale ci devin efective;
Constructorul poate fi considerat o metoda mai speciala. Aceasta nu are
tip la definire. Constuctorul este folosit in primul rand pentru a defini o
instanta a clasei in care este scris si de asemenea ca instructiuni ale
constructorului putem scrie linii de cod care sa se execute la creare
instantei. De exemplu am putea da valori atributelor instantei in momentul
crearii lor. Constructorul are intotdeauna acelasi nume cu al clasei in care
se afla si poate primi parametri care sunt considetati pentru instructiuni
valori cunoscute. Orice clasa are un constructor denumit constructor

implicit, care nu primeste parametri si nu executa nimic, dar cu ajutorul


caruia se pot crea instante ale clasei. Odata definit un alt constructor in
clasa, constuctorul implicit nu mai exista.

Accesul la atribute si apelul comportamentelor

Accesul la atribute se poate face folosind operatorul . (punct);


Operatorul . (punct) se numeste si operator de dereferentiere. Cu ajutorul
lui se poate face referirea la un atribut al unei instante sau la un
comportament al unei instante.
Un comportament nu poate fi apelat fara existenta unei instante.

Zone de memorie de clasa

Zonele de memorie de clasa se mai numesc si zone de memorie statice,


deoarece se creaza folosind modificaorul static. O zona de memorie de
clasa nu reprezinta un atribut. Valoarea acesteia este comuna in toate
instantele definite de clasa. Deoarece valoarea ei este unica, o variabila
statica poate fi dereferentiata direct din clasa.

Metode de clasa

Pana acum metodele definite reprezentau comportamente ale instantelor


definite cu clasa in care acestea erau create. Exista totusi posibilitatea de a
defini metode care nu reprezinta comportamente. Acestea se numesc
metode statice sau de clasa, se creaza folosind modificatorul static si nu
pot folosi decat alte sintaxe tot statice. Cu alte cuvinte o metoda de clasa
nu poate accesa atributele clasei sau comportamentele definite in clasa.
Cea mai importanta dintre metodele de clasa este metoda principala a
programului
main().
Deoarece
metodele
statice
nu
reprezinta
comportamente acesta pot fi dereferentiate, similar variabilelor statice,
folosind numele clasei in care se afla.

O variabila poate fi definita:

global (in interiorul clasei)

local (in interiorul unei metode sau structuri)

Daca variabila este definita direct in interiorul clasei ea este accesibila de


catre toate metodele din clasa. Daca este definita intr-o metoda sau o
structura atunci variabila este vizibila numai local, in structura care o
defineste. Daca exista o variabila globala si una locala cu acelasi nume
atunci cea accesata este intotdeauna cea mai locala. Prin urmare exista
posibilitatea de a defini variabile cu acelasi nume doar daca sunt in domenii
de vizibilitate diferite.
In cazul de mai sus este exemplificat modul de definire global si local al
variabilelor. In structura while, variabila x folosita este cea definita in
interiorul structurii. Acea variabila este vizibila numai in structura while,
fiind inaccesibila in afara acesteia.
O variabila definita local nu are valoare implicita. Folosirea acesteia in
operatii fara a-i atibui o valoare duce la aparitia unei erori de sintaxa.
Variabilele definite global (precum atributele) au valori implicite in functie
de tipul de data:
Pentru:

int, long, short, byte valoarea implicita este 0

float si double valoare implicita este 0.0

char valoarea implicita este '/u0000'

boolean valoarea implicita este false

orice tip de obiect valoarea implicita este null

Supraincarcare (overloading)

Supraincarcarea reprezinta posibilitatea de a defini mai multe metode in


aceeasi clasa care au acelasi identificator dar difera prin parametri. Daca
doua metode diferite au parametrii diferiti atunci ele pot avea acelasi

nume. Parametrii pot fi diferiti fie prin tipul fie prin numarul fie prin ordinea
lor.
Supraincarcarea este un procedeu care se poate aplica si constructorilor.
Constructorii oricum sunt fortati sa aiba acelasi nume cu al clasei. Asadar
folosind supraincarcarea in cazul constructorilor sinugurul lucru care trebuie
avut in vedere este definirea folosind parametrii diferiti ca in cazul
metodelor.

Tablouri

Un tablou reprezinta o colectie de variabile de acelasi tip. Exista


pozibilitatea de a defini o structura de un numar definit de variabile de un
anumit tip. Aceste tipuri de structui de date se numesc tablouri (in
engleza arrays).
Clasificam tablourile dupa numarul lor de dimensiuni:

unidimensionale - vectori

bidimensionale - matrice

pluridimensionale

Parcurgerea unui vector se poate face folosind o structura repetitva for,


deoarece indecsii se gasesc intotdeauna intr-un interval continuu de numere.
Tablouri bidimensionale:

pot fi considerate vectori de vectori

au doua dimensiuni cu lungime proprie

fiecare dimensiune este indexata incepand cu valoare 0

intervalul indecsilor este intre 0 si lungimea 1

Instanta this reprezinta intr-o clasa instanta curenta. Practic, folosita intr-un
comportament aceasta este instanta care se comporta (cea al carei
comportament este apelat). Folosita intr-un constructor this reprezinta

instanta care este construita. Nu uitati ca this nu poate fi accesat din metode
statice sau contexte statice.
Constructorul this()
this() reprezinta consructorul clasei curente.

Tipul enum

O enumerare reprezinta un tip de data care poate lua numai anumite


valori precizate prin sintaxa la definirea enumerarii.

Pachete - managementul claselor

Pachetele reprezinta colectii de clase. Acestea sunt utile in principal


pentru managementul numelor. Doua clase pot fi definite cu acelasi nume
daca apartin de pachete diferite. In felul acesta folosirea pachetelor
micsoreaza posibilitatea aparitiei conflictelor de nume prin divizarea zonelor
de conflict. Fiecare pachet reprezinta o zona de conflict (un pachet nu poate
contine clase cu acelasi nume). Pentru a specifica unei clase pachetul din
care apartine se foloseste instructiunea package. Aceasta este folosita
intotdeauna pe prima linie a fisierului cu extensia .java. Mai important,
pentru acest curs este insa modul in care pot fi folosite clase din anumite
pachete.
Pentru a putea folosi in orice mod o clasa a unui anumit pachet (membri
ai clasei) este necesar importul clasei. Prin import se precizeaza practic
care este pachetul din care apartine clasa utilizata in scrierea codurilor
sursa. In urmatorul modul vor fi folosite clase din API-urile platformei SE
(Standard Edition). Instructiunea prin care se efectueaza importul unei clase
este:
import <nume_pachet>.<nume_clasa>;
Exemplu:
daca
pachetul
se
numeste java.awt si
clasa
numeste Graphics, pentru a folosi membri ai clasei va trebui scris:
import java.awt.Graphics;

se

Importurile se fac in fisierul .java in care este scrisa clasa, inainte de linia
de definire a clasei.
Accesul la informatie si comportament

Modificatorii de acces reprezinta cuvinte cheie prin intermediul carora se


poate preciza cine (ce pachet/clasa/metoda) are acces la un anumit
membru. Exista trei modificatori de acces:

public

protected

private

Acestia se plaseaza la definirea unui membru al unei clase (zona de


memorie sau metoda) si precizeaza cine poate accesa acel membru.
public este modificatorul care permite accesul oricui si oriunde. Daca o
zona de memorie sau metoda este facuta public atunci aceasta poate fi
accesata de orice clasa a aplicatiei, din orice pachet.
private este modficatorul care restrange accesul la un membru numai in
interiorul clasei. Doar clasa care defineste acea zona de memorie/metoda are
accesa la ea.
protected este modul in care un membru poate fi accesat numai de
clasa care il defineste sau de clasa care mosteneste clasa ce il defineste.
Mostenirea este prezentata in acest modul il lectiile urmatoare.
In cazul in care nu se precizeaza un modificator de acces, membrul este
considerat a fi in modul default care permite accesul la membrul respectiv
similar cu public, dar numai la nivelul pachetului.
In exemplele din imaginile de mai sus sunt prezentati modificatorii numai
pentru
variabile,
in
acelasi
mod
acestia
pot
fi
folositi
si
pentru constante saumetode.
Encapsularea (incapsulare)

Din punctul de vedere al securitatii, limbajul de programare Java este


proiectat cu un principiu numit "sandbox" (groapa cu nisip). Programul scris
in Java poate fi comparat cu un copil care se joaca in groapa cu nisip, iar
utilizatorul cu parintele. In acest fel, copilul este protejat din punctul de
vedere al parintelui, dar si parintele este protejat, deoarece copilul sta
linistit si se joaca.
Encapsularea este procesul de ascundere a informatiilor in clasa pentru
care se ofera acces indirect prin intermediul unor metode numite "iterator
methods". Informatiile (atributele) clasei pot fi ascunse prin intermediul
modificatorului e acces private. In felul acesta atributele nu vor mai putea
fi accesate decat de clasa in care sunt definite. Exista doua tipuri de
"iterator methods": getters/ accessors si setters/mutators.
Mutatorii sunt metode definite pentru modificarea valorii unui atribut
privat. Pentru a putea fi accesate de catre alte clase, standard iterator
methods sunt intotdeauna definite public. Mutatorii sau setarii sunt de tip
void doarece nu returneaza nimic si primesc intotdeauna ca parametru o
variabila de tipul atributului pentru care este creat. Pentru fiecare atribut
privat trebuie creat un mutator si un accesor.
Accesorul este metoda folosita pentru a accesa (prelua) valoarea
atributului privat pentru care este creata. Accesorul este intotdeauna de
tipul variabilei a carei valori o returneaza si nu primeste parametri. Rolul
accesorului este de a returna valoarea variabilei privata.
Prin conventie identificatorii mutatorilor incep cu cuvantul set si continua cu
numele variabilei pentu care sunt construiti. Identificatorii accesorilor incep
cu cuvantul get si sunt urmati de numele variabilei pentru care sunt definiti
pentru toate tiprile de date mai putin boolean. Pentru variabile de tip
boolean idntificatorul accesorului incepe standard cu is.

Mostenirea (extends)

Mostenirea este un procedeu specific programarii orintate pe obiecte. O


clasa care mosteneste o alta clasa preia atributele si comportamentele
neprivate de la aceasta. Mostenirea se face prin folosirea cuvantului
cheie extends.
Un membru privat nu poate fi mostenit. Daca modificatorul de vizibilitate al
membrului nume din clasa Forma este facut private, variabila nu va mai fi
mostenita.
Cuvantul cheie super

In urma studiului mostenirii se poate pune urmatoarea problema. In


programul de mai jos clasa care mosteneste defineste un membru ce are
acelasi identficator cu membrul mostenit.
super este cuvant cheie si nu poate fi folosit ca identifcator.

Constructorul super()

Asa cum this() poate fi folosit pentru a se face referire la unul dintre
constructorii clasei curente, super() poate fi folosit pentru a face referire la
unul dintre constructorii clasei superioare. super() nu poate fi apelat decat
pe prima linie a constructorului clasei copil. Acest lucru este datorat
modului in care se face instantierea pentru o clasa care mosteneste o alta
clasa:
1. In momentul in care constructorul clasei copil este apelat acesta cauta
pe prima linie a constructorului apelul pentru constructorul clasei
superioare, in cazul in care nu gaseste apelul se apeleaza automat
constructorul implicit, daca acesta nu exista rezultatul este o eroare la
compilare.
2. Este creata instanta super.
3. Este creata instanta this.

Suprascrierea (overriding)

Cand o clasa mosteneste o alta clasa preia toate metodele neprivate.


Exista insa posibilitatea de a redefini comportamentul unei metode (setul
de instructiuni), pastrand insa identifiatorul. Rescrierea comportamentului
unei metode mostenite, pastrand insa semnatura metodei se numeste
supraincarcare.
Clase abstracte
In general, dupa cum a fost prezentat in acest curs, clasele sunt folosite
pentru definirea obiectelor si crearea instantelor care interactioneaza
pentru a forma aplicatia. Exista totusi si clase care nu pot fi instantiate.
Aceste tipuri de clase se numesc clase abstracte si sunt folosite pentru a
generaliza atribute si comportamente. Cu alte cuvinte, o clasa abstracta
este creata nu pentru a fi instantiata ci numai pentru a fi mostenita. Prin
modul in care este definita poate cumula atribute sau comportamente
comune mai multor tipuri de obiecte. Prin definirea lor intr-o clasa
abstracta, acestea sunt scrise doar o singura data, urmand ca obiectele
care au nevoie de acestea la definire sa le mosteneasca de la clasa
abstracta.
Mai mult decat atat, clasele abstracte pot defini comportamente
abstracte. Comportamentele abstracte sunt acele tipuri e comportamente
care nu sunt definite in intregime. Clasa defineste doar antetele lor
(modificatori, tip, identificator si parametri) fara a da insa un set de
instructiuni. Orice clasa neabstracta care mosteneste de la clasa abstracta
aceste comportamente trebuie sa suprascrie comportamentele abstracte.
Deoarece o instanta este o entitate neabstracta si prin urmare nu are voie
sa aiba comportamente abstracte. Din acest motiv comportamentele
abstracte trebuiesc suprascrise de catre orice clasa care poate defini
instante. O clasa care nu suprascrie comportamente abstracte mostenite
trebuie definita abstract.
Clasele si comportamentele abstracte sunt definite folosind cuvantul
cheie abstract.
Implementarea interfetelor
O interfata este similara unei clase abstracte. Diferenta dintre o clasa
abstracta si o interfata este ca interfata nu contine decat
comportamente abstracte sau constante. Metodele intr-o interfata sunt
considerate abstracte, dar pentru definirea lor nu mai este folosit cuvantul
cheie abstract.

Polimorfismul este aplicabil si in cazul interfetelor: O zona de memorie dintr-o


interfata mostenita poate contine instate ale clasei ce o mosteneste, daca
clasa ce o mosteneste nu este abstracta.
Mostenirea interfetelor
O interfata poate mosteni una sau mai multe interfete. Mostenirea intre
interfete se face ca in cazul claselor prin folosirea cuvantului
cheie extends. In acest caz insa, mostenirea se poate face multiplu.

Clase finale
O clasa care este finala nu poate fi mostenita. Clasele finale sunt create
prin folosirea modificatorului final. O clasa nu poate fi niciodata
si final si abstractin acelasi timp.

Clasa nu poate fi mostenita si nu poate fi abstracta.

You might also like