Upload
others
View
36
Download
0
Embed Size (px)
Citation preview
1
Structuri de Date în Java (III)● Definirea unei clase (complet)● Supraîncărcarea (overloading)● Modificatori de acces● Moştenire. Interfeţe● Clase abstracte● Polimorfism● Suprascrierea (overriding)● Clasa Object. Metode suprascrise: toString, clone, equals● Compile time vs. runtime● Moştenire vs. compoziţie● Excepţii. Specificare şi tratare● Nested classes vs. inner classes● Clase locale şi clase anonime
2
Definirea unei clase
● Şablonul definirii unei clase:
[<tip acces>] [abstract / final] class <className>[extends <superClassName>][implements <interfaceNames>] {
// constructori// metode// variabile membre
}
3
Supraîncărcarea (overloading)
● O clasă poate avea două metode cu acelaşi nume doar dacă listele lor de parametri sunt diferite
● Exemplu:● void maxx () { ... }● void maxx (int x) { ... }● Java ştie care metodă o va chema pe baza
semnăturii● Exemplu:● maxx (7); // cheamă a doua metodă
4
Constructori supraîncărcaţi
● O clasă poate avea mai mulţi constructori:
public class BankAccount {private int amount = 10;// iniţializare înainteapublic BankAccount () { // constructorului
// ...}public BankAccount (int amount) {
this.amount = amount;}
5
Tipuri de acces
● Membrii unei clase pot avea diferite tipuri de acces
● Există patru tipuri de acces:● public – orice clasă din orice pachet● protected – orice clasă derivată (subclasă) are
acces● (default) – doar clasele din acelaşi pachet● private – accesibil doar din interiorul clasei
6
Moştenire
● Permite claselor să definească aceeaşi funcţionalitate ca şi clasa de bază
● Scade complexitatea sistemelor mari
● Derivare:● Java permite doar o singură clasă de bază● Se defineşte cu cuvântul cheie extends
7
Interfeţe● Interfaţa este specificarea unei clase● Declară metodele (publice) dar nu le defineşte● Interfeţele nu au constructori● O clasă ce implementează o interfaţă trebuie să-i
definească metodele● Şablon:
[<tip acces>] interface <interfaceName>[extends <interfaceNameList>] {
// declaraţii de metode// declaraţii de constante
}
8
Exemplu de interfaţă
public interface BankAccount {public void withdraw (int amount);public void deposit (int amount);public int getBalance ();public final int maxNoOfWithdraws = 5;
}
// constanta din interfaţă se iniţializează la declarare
9
Implementarea interfeţeipublic class CheckingAccount implements BankAccount {
private int balance;public CheckingAccount (int initial) {
balance = initial;}// implementăm toate metodele interfeţei BankAccountpublic void withdraw (int amount) {
balance -= amount; // puteam scrie balance = balance - amount
}public void deposit (int amount) {
balance += amount; // similar, balance = balance + amount}public int getBalance () {
return balance;}
}
10
Clase abstracte● Sunt o îngemănare a claselor şi interfeţelor● pot avea metode definite (cu corp)● pot avea variabile membre
● Se definesc ca şi o clasă, prefixată însă cu cuvântul cheie abstract
● Conţin cel puţin o metodă nedefinită (doar declarată), definind însă metodele comune cunoscute
11
Exemplu de clasă abstractăpublic abstract class BankAccount {
protected int balance;public int getBalance () {
return balance;}public void deposit (int amount) {
balance += amount;}public void withdraw (int amount); //
abstractă}
12
Derivare din clasă abstractăpublic class SavingsAccount extends BankAccount {
private int numberOfWithdrawals;public SavingsAccount () {
balance = 0;numberOfWithdrawals = 0;
}public void withdraw (int amount) { // trebuie definită
if (numberOfWithdrawals > 5) {throw new RuntimeException (“too many withdrawals”);
} else {balance -= amount;numberOfWithdrawals ++;
}}public void resetNumOfWithdrawals () {…}
}
13
Polimorfism
● Obiecte de diferite tipuri folosesc aceleaşi metode (în fapt cu aceeaşi semnătură dar implementări diferite)
● Posibilitatea de a extinde sau suprascrie funcţionalitatea din clasa de bază (super – clasă)
● Java are grijă să discrearnă care din metodele suprascrise se vor rula efectiv
14
Clasa Object
● Orice definiţie de clasă implicit extinde clasa java.lang.Object
● Clasa de bază java.lang.Object defineşte metode pe care le moştenesc toate clasele:
● clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait
15
Suprascrierea (overriding)● Superclasă● dacă B extinde clasa A, spunem că A este
superclasa lui B● clasa B este subclasa lui A
● Dacă avem în clasa A o metodă cu semnătura:public void foo (int arg)● Atunci clasa B poate suprascrie metoda prin
definirea unei metode cu aceeaşi semnătură
● Nu confundaţi suprascrierea cu supraîncărcarea!
16
Metoda toString● Implementată de clasa Object● Este apelată atunci când este nevoie de conversia acestui
tip de dată la tipul String● De regulă e necesară suprascrierea celei originale
class Account {public String toString () { return “account”; }
}
Account a = new Account ();System.out.println (a);System.out.println (a.toString ()); // valid, dar nenecesar
17
Metoda clone● Clonarea se foloseşte pentru crearea unei copii bit cu bit identice
a obiectului
public Location implements Cloneable {public Object clone () {
Location answer;try {
answer = (Location)super.clone (); // typecast} catch (CloneNotSupportedException e) {
throw new RuntimeException ("class not cloneable"); } return answer;
}}
18
Metoda equals
public boolean equals (Object o);
● Toate clasele moştenesc această metodă din clasa Object
● Implicit, ea realizează testul asupra egalităţii dintre referinţe, adică verifică dacă două referinţe “arată” spre acelaşi obiect din memorie
● Trebuie suprascrisă în cazul în care se doreşte verificarea egalităţii între două instanţe diferite ale clasei
19
Implementarea implicită
CheckingAccount c1 = new CheckingAccount (100);CheckingAccount c2 = new CheckingAccount (100);
c1.equals (c1); // truec2.equals (c2); // truec1.equals (c2); // false
● Două obiecte de tip CheckingAccount ar trebui să fie egale dacă au aceeaşi sumă în ele!
20
Suprascrierea metodei equals
public class CheckingAccount extends BankAccount {// …public boolean equals (Object o) {
if (o instanceof CheckingAccount) {CheckingAccount c = (CheckingAccount)o;return balance == c.balance;
} else{return false;
}}// …
}
21
Efectul metodei suprascrise
CheckingAccount c1 = new CheckingAccount (100);CheckingAccount c2 = new CheckingAccount (100);
c1.equals (c1); // truec2.equals (c2); // truec1.equals (c2); // true
22
Un alt fel mai general de a crea obiectele
Object o1 = new CheckingAccount (100);Object o2 = new CheckingAccount (100);
o1.equals (o1); // trueo2.equals (o2); // trueo1.equals (o2); // true
● Totuşi se cheamă metoda suprascrisă din clasa CheckingAccount chiar dacă referinţa o1 sau o2 este de tip Object
● Java “ştie” că de fapt în spate este un obiect de tip CheckingAccount
23
Compile time vs. run-time
● Compile timeTipul de dată este stabilit la momentul scrierii
codului (la compilare)
● RuntimeCompilatorul nu cunoaşte ce fel de obiect se va
stoca de fapt într-o referinţă declarată generic de tip Object
24
Method dispatching
● Java cheamă metoda pentru obiectul al cărui tip se determină la runtime
public abstract class BankAccount {// ...public void withdraw (int amount) { ... }// ...
}
● Clasele CheckingAccount şi SavingsAccount suprascriu metoda withdraw
25
Exemplu: BankAccount
BankAccount b1 = new CheckingAccount (10);BankAccount b2 = new SavingsAccount (10);
b1.withdraw(5);// cheamă CheckingAccount.withdraw(int)
b2.withdraw(5);// cheamă SavingsAccount.withdraw(int)
26
Apel de metodă cu tip generic
public boolean deleteAccount (BankAccount accnt) {// ...
}
BankAccount c = new CheckingAccount (20);// ...manager.deleteAccount (c);
● Metoda se poate apela cu obiecte de tipul SavingsAccount sau CheckingAccount, compilatorul nu are de unde să ştie asta
27
Avantajele folosirii tipurilor generice
● Se poate schimba implementarea mai târziu (sau se scrie altă implementare)
● Nu trebuie schimbat nimic în codul care foloseşte tipul generic
● Se pot defini componente de tip plug-in pentru care specificăm doar metodele interfeţei, se poate ulterior crea orice implementare a acesteia
28
Moştenire vs. compoziţie
● Moştenirea● se foloseşte când clasa derivată specializează clasa de
bază, păstrînd unele din metodele originale● avantajul e că nu trebuie să scriem prea mult cod în noua
clasă pentru că “vine de-a gata” funcţionalitatea existentă deja
● Compoziţia● conţine o clasă, procedeu folosit când clasa defineşte noi
comportamente bazîndu-se pe mai multe clase
29
Exemplu de moştenireclass Rectangle {
public int width, height; public Rectangle (int width, int height) {
this.width = width; this.height = height;
}public int circumference () { return (width + height) * 2; }
}class Square extends Rectangle {
Square (int x) {super (x, x); // cheamă constructorul super-clasei
}}
Square square = new Square (3); circumference (sq); // întoarce 12, ok
30
Exemplu de compoziţie
class Geometric {public Rectangle r; // noile obiecte sunt datepublic Square s; // ca variabile membrepublic Geometric (int width, int height) {
r = new Rectangle (width, height);s = new Square (width);
}public int circumference () {
return s.circumference () + r.circumference ();}
31
Excepţii● Scop: ajută programatorul în a raporta şi trata erorile● Ce se întâmplă la aruncarea unei excepţii?● firul normal de execuţie al programului se întrerupe● se caută un handler de tratare:try {
// acţiuni care pot arunca excepţia} catch (<tip excepţie A> name) {
// tratează excepţia A} catch (<tip excepţie B> name) {
// tratează excepţia B} finally {
// acţiuni care se execută după ce s-a tratat// oricare din excepţii
}
32
Prinderea excepţieiclass Editor {
public boolean openFile (String filename ) {try {
boolean fileOpen = true;File f = new File (filename);// alte activităţi cu freturn true;
} catch (FileNotFoundException e) { e.printStackTrace ();return false;
} finally { fileOpen = false;
}System.out.println (“bar“);
}}
33
Aruncarea excepţiei
public class File {public File (String filename) throws
FileNotFoundException {// …if ( can’t find file ) {
throw new FileNotFoundException (); }
}}
// declaraţia throws instruieşte compilatorul să asigure că// programul ce foloseşte clasa face şi tratarea excepţiei
34
Clase conţinute (nested- sau inner- classes)
class EnclosingClass {// ...class NestedClass {
// ...}// ...
}
35
Nested classes (încuibărite)
● Au acces la toţi membrii clasei ce o conţine, chiar dacă aceştia sunt private
● Pot fi declarate static (sau final, abstract)● Clasele nested ne-statice se numesc inner-classes
class EnclosingClass {static class StaticNestedClass { ... }class InnerClass { ... }
}
36
Inner classes
● Sunt asociate cu o instanţă a clasei● Nu pot declara membri statici● Pot fi instanţiate doar în contextul clasei care o
conţine
Outer class Inner class
37
Clase inner locale● Presupunem cunoscută declaraţia interfeţei Iterator
public class Stack {private ArrayList items; public Iterator iterator () {
private class StackIterator implements Iterator {int currentItem = items.size() - 1;public boolean hasNext () { ... }public ArrayList<Object> next() { ... }public void remove () { ... }
}return new StackIterator ();
}// clasa inner se poate declara şi aici
}
38
Clase inner anonime● Se doreşte ca rezultatul întors să fie un obiect cu tip clasă ce
implementează interfaţa Iterator● Lipseşte numele clasei!
public class Stack {private ArrayList items;public Iterator iterator () {
return new Iterator() {int currentItem = items.size() - 1;public boolean hasNext() { ... }public ArrayList<Object> next () { ... }public void remove () { ... }
};}
}