Sunteți pe pagina 1din 55

Proiectarea aplicațiilor orientate

obiect
Curs 4 – Mostenire

J
J Acest curs
› Mostenire in Java
› Constructori
J Mostenire
› Mostenirea este mecanismul fundamental pentru
refolosirea codului.
› Prin mostenire o clasa noua dobandeste toate atributele si
comportamentul unei clase existente (clasa originala).
› Din acest motiv, noua clasa poate fi creata prin simpla
specificare a diferentelor fata de clasa originala din care
provine.
› Datorita relatiilor de mostenire clasele de obiecte sunt
organizate intr-o ierarhie bine precizata.
J Mostenire
› In cadrul ierarhiei claselor de obiecte, operatia de definire a
unei noi clase de obiecte pe baza uneia deja existente se
numeste derivare.
› Clasa originala (mai generala) se va numi superclasa a noii
clase, iar noua clasa de obiecte se va numi subclasa a
clasei din care deriva.
› Uneori, in loc de derivare se foloseste termenul de
extindere.
J Mostenire
› Termenul vine de la faptul ca o subclasa isi extinde
superclasa cu noi variabile si metode.
› De exemplu putem extinde clasa Patrulater:
– la Patrat
– si Dreptunghi
› Intr-o ierarhie de clase, o clasa poate avea o singura
superclasa, insa poate avea un numar nelimitat de
subclase.
J Mostenire
› Subclasele mostenesc toate atributele si metodele
superclasei lor, care la randul ei mosteneste toate
atributele si metodele de la superclasa ei si asa mai
departe, urcand in ierarhie.
› Rezulta ca o clasa nou creata contine toate atributele si
metodele claselor aflate deasupra sa in ierarhie, si in plus
contine propriile atribute si metode.
J Mostenire

› Clasa A este superclasa a clasei B


› Clasa B este subclasa a clasei A
› Clasa B este superclasa pentru clasele C, D si E
› Clasele C, D si E sunt subclase ale clasei B
J Mostenire
› Reprezentarea relatiei de mostenire folosind diagrama
UML
J Mostenire
J Mostenire
› Principalele caracteristici ale unei ierarhi de clase sunt:
– atributele si metodele comune mai multor clase pot fi definite in
superclase, care permit folosirea repetata a acestora pentru toate
clasele aflate pe nivelele mai joase din ierarhie
– modificarile efectuate in superclasa se reflecta automat in toate
subclasele ei, subclasele acestora si asa mai departe; nu trebuie
modificat si recompilat nimic in clasele aflate pe nivelurile
inferioare, deoarece acestea primesc noile informatii prin
mostenire
J Mostenire
› clasa derivata poate sa adauge noi atribute si metode si
poate modifica semnificatia metodelor mostenite (prin
polimorfism);
› superclasa nu este afectata in nici un fel de modificarile
aduse in clasele derivate;
› o clasa derivata este compatibila ca tip cu superclasa,
ceea ce inseamna ca o variabila referinta de tipul
superclasei poate referi un obiect al clasei derivate, dar nu
si invers; clasele derivate dintr-o superclasa nu sunt
compatibile ca tip.
J Mostenire
› In varful ierarhiei de clase Java se afla clasa Object, iar
toate clasele de obiecte, care se creeaza, sunt derivate din
aceasta unica superclasa.
public class Object{
public Object();
protected Object clone();
boolean equals(Object obj)
protected void finalize()
Class<?> getClass()
int hashCode()
void notify()
void notifyAll()
void wait()
void wait(long timeout)
void wait(long timeout, int nanos)
}
J Class Object
› protected Object clone() throws CloneNotSupportedException
› Creaza si returneaza o copie a obiectului respectiv
› Nu s-a utilizat cuvantul copy deoarece aceasta actiune poate fi
dependenta de obiect/context
x.clone() != x
X.clone().getClass() == x.getClass()
x.clone().equals(x) == true
› Returneaza o clona a instantei
› Arunca CloneNotSupportedException daca obiectul nu suporta
Clonable interface
J Class Object
› public boolean equals(Object obj)
› Indica daca doua obiecte sunt egale din punct de vedere al
continutului
› In clasa Object functia verifica daca cele doua obiecte sunt egale
din punct de vedere al adresei de memorie
› Functia trebuie suprascrisa in clasa derivata pentru a verifica
egalitatea din punct de vedere al continutului
J Class Object
Test test1 = new Test(3);
Test test2 = new Test(3);
// comparatia va fi efectuata doar din perspectiva egalitatii adresei

if(test1.equals(test2)){
System.out.println("test1 and test2 are true in .equal");
}

//suprascrierea metodei pentru comparatia continutului (atributelor)

public boolean equals(Object object) {


if(object instanceof Test && ((Test)object).t == this.t) {
return true;
} else {
return false;
}
}
J Class Object
› public int hashCode()
– Returneaza o valoare hash code a obiectului. Daca doua obiecte sunt egale din
p.d.v al metodei equal() atunci si valorile hash code returnate sunt identice

› protected void finalize() throws Throwable


– Metoda este apelata de garbage collector
– O subclasa trebuie sa suprascrie aceasta metoda pentru a curata/inchide
resurse sistem
J Class Object
public class Test{
public static void main(String[] args){
Test t = new Test();
System.out.println(t.hashCode());

t = null;
// calling garbage collector
System.gc();
System.out.println("end");
}

@Override
protected void finalize()
{
System.out.println("finalize method called");
} 366712642
} end
finalize method called
J Class Object
› public final Class<?> getClass()
› Returneaza clasa de runtime a obiectului

public class Test


{
public static void main(String[] args)
{
Object obj = new String(“abcd");
Class c = obj.getClass();
System.out.println("Class of Object obj is : " + c.getName());
}
}

Class of Object obj is : java.lang.String


J Class Object
› public String toString()
› Returneaza o reprezentare sub forma de string a obiectului
› Se recomanda ca toate subclasele sa suprascrie aceasta metoda
› Metoda toString() pentru o clasa object returneaza un string ce
consta in:

// Default behavior of toString() is to print class name, then


// @, then unsigned hexadecimal representation of the hash code
// of the object
public String toString(){
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
public class Student {

J static int last_roll = 100;


int roll_no;

Student(){
roll_no = last_roll;
last_roll++;
}

@Override
public int hashCode(){
return roll_no;
}

public static void main(String args[]){


Student s = new Student();
// Below two statements are equivalent
System.out.println(s);
System.out.println(s.toString());
} Student@64
} Student@64
J Class Object
› Orice clasa este direct sau indirect derivata din Object
class
› Daca o clasa nu extinde (in mod explicit) nici o alta clasa,
atunci aceasta extinde in mod direct clasa Object
› O clasa derivata dintr-o clasa, derivata dintr-o clasa ….
derivata din Object se numeste descendent class
J Class Object
class Fruit
{
public Fruit()
{
System.out.println("Super class constructor");
System.out.println("Super class object hashcode :" + this.hashCode());
System.out.println(this.getClass().getName());
}
}
class Apple extends Fruit
{
public Apple()
{
System.out.println("Subclass constructor invoked");
System.out.println("Sub class object hashcode :" + this.hashCode());
System.out.println(this.hashCode() + " " + super.hashCode());
System.out.println(this.getClass().getName() + " " +
super.getClass().getName());
}
}
J Class Object
public class Test
{
public static void main(String[] args)
{
Apple myApple = new Apple();
}
}

Super class constructor


Super class object hashcode :366712642 Apple
Subclass constructor
Subclass object hashcode :366712642 366712642
Apple Fruits
J Class Object
› Apelurile metodelor hashCode au acelasi rezultat atat pentru metoda
apelata in clasa de baza cat si pentru cea din clasa derivata
› Obiectul este o instanta a clasei Apple motiv pentru care
super.getClass().getName()
› returneaza Apple
J Constructori
› Constructorul clasei de baza cu lista vida de argumente
este automat apelat in constructorul clasei derivate
class Base {
Base() {
System.out.println("Base Class Constructor Called ");
}
}
class Derived extends Base {
Derived() {
System.out.println("Derived Class Constructor Called ");
}
}
public class Main {
public static void main(String[] args) {
Derived d = new Derived();
Base Class Constructor Called
}
Derived Class Constructor Called
}
J Constructori
› Apelul unui constructor cu parametri trebuie precizat in mod explicit
› Se realizeaza folosind cuvantul cheie super()
› Trebuie sa fie prima linie in constructorul clasei derivate

class Base
{
int x;
Base(int _x)
{
x = _x;
}
}
J Constructori
class Derived extends Base {
int y;
Derived(int _x, int _y) {
super(_x);
y = _y;
}
void Display() {
System.out.println("x = "+x+", y = "+y);
}
}

public class Main


{
public static void main(String[] args)
{
Derived d = new Derived(10, 20); x = 10, y = 20
d.Display();
}
}
J Suprascrierea functiilor
//base class
class Parent
{
void show()
{
System.out.println("Parent's show()");
}
}

// Inherited class
class Child extends Parent
{
@Overide
// This method overrides show() of Parent
void show()
{
System.out.println("Child's show()");
}
28
}
J Suprascrierea functiilor
class Main
{
public static void main(String[] args)
{
// If a Parent type reference refers
// to a Parent object, then Parent's
// show is called
Parent obj1 = new Parent();
obj1.show();

// If a Parent type reference refers


// to a Child object Child's show()
// is called. This is called RUN TIME
// POLYMORPHISM.
Parent obj2 = new Child();
obj2.show();
} Parent's show()
} Child's show() 29
J Redefinire partiala a unei metode
› Redefinirea parţială inseamna ca metoda din clasa derivata
nu redefineste complet metoda cu aceeasi semnatura din
superclasa, ci extinde operatiile pe care aceasta le
realizeaza.
› Cu alte cuvinte, metoda din clasa derivata face ceva in plus
fata de cea originala din superclasa.
› Pentru a apela metoda din superclasa in interiorul metodei
din clasa derivata se foloseste referinta super.
class A
{

J int x = 0;
int y = 1;

void afisareDate()
{
System.out.println("Sunt un obiect al clasei " +
this.getClass().getName());
System.out.println("x este " + x);
System.out.println("y este " + y);
}
}
class B extends A
{
int z = 3;

void afisareDate()
{
super.afisareDate();
System.out.println("z este " + z);
}

}
Accesul la metodele din superclasă şi
J redefinirea metodelor în clasele derivate
› Atunci cand se creaza o clasa derivata si se redefineste (suprascrie)
o metoda declarata intr-o superclasa, trebuie sa se ia in considerare
tipul de acces dat pentru metoda originala.
› 1. metodele de tip public dintr-o superclasa trebuie sa fie, de
asemenea, de tip public in toate clasele derivate; ele nu pot fi
redefinite de tip private in clasele derivate;
› 2. metodele de tip protected dintr-o superclasa pot fi de tip
protected sau de tip public in clasele derivate; ele nu pot fi
redefinite de tip private in clasele derivate;
› 3. metodele de tip private dintr-o superclasa nu pot fi redefinite
(suprascrise) in clasele derivate
J Some Interesting Facts:
› 1. In C++ este necesar cuvantul virtual pentru polimorfism, in java
metodele sunt implicit virtuale
› 2. Suprascriere multi-nivel
// Base Class
class Parent
{
void show() { System.out.println("Parent's show()"); }
}

// Inherited class
class Child extends Parent
{
// This method overrides show() of Parent
void show() { super.show();System.out.println("Child's show()"); }
}
33
J Some Interesting Facts:
// Inherited class
class GrandChild extends Child
{
// This method overrides show() of Parent and Child
void show() { super.show();System.out.println("GrandChild's show()"); }
}

// Driver class
class Main
{
public static void main(String[] args)
{
Parent obj1 = new GrandChild();
obj1.show();
}
} Parent's show()
Child's show()
GrandChild's show() 34
J Some Interesting Facts:
› 3. Daca se doreste ca o metoda sa nu mai fie suprascrisa
se va declara ca fiind final
class Parent
{
// Can't be overridden
final void show() { }
}

class Child extends Parent


{
// This would produce error
void show() { } 13: error: show() in Child cannot override
} show() in Parent
void show() { }
^
overridden method is final 35
J Some Interesting Facts:
› 4. Unei metode suprascrise nu se poate preciza un
specificator de acces mai slab dar invers este posibil
// This program won't compile as we have
// given weaker access in derived class
class Parent
12: error: show() in Child cannot override
{
show() in Parent
// Can't be overridden
private void show() { }
protected void show() { }
^
}
attempting to assign weaker access
privileges; was protected
class Child extends Parent
1 error
{
// This would produce error. If we
// replace private with protected or
// public, the program would work.
private void show() { }
} 36
J Some Interesting Facts:
› 5. Metodele nu pot fi suprascrise in inner class
› 6. Pentru metodele declarate cu static si care au aceeasi
semnatura cu cele din clasa de baza nu exista run-time
polimorfism
› 7. Se poate apela o metoda suprascrisa din clasa de baza
folosind cuvantul cheie super
// Base Class
class Parent
{
void show()
{
System.out.println("Parent's show()");
}
} 37
J Some Interesting Facts:
// Inherited class
class Child extends Parent
{
// This method overrides show() of Parent
void show()
{
super.show();
System.out.println("Child's show()");
}
}
// Driver class
class Main
{
public static void main(String[] args)
{
Parent obj = new Child();
obj.show();
Parent's show()
}
Child's show() 38
}
J C++ vs. Java
› 1. In Java toate clasele sunt derivate direct sau indirect din
clasa Object. In C++ nu exista o clasa de baza unica, iar la
definirea unei clase nu mosteneste in mod automat o alta
clasa
class Test {
// members of test
}
class Main {
public static void main(String[] args) {
Test t = new Test();
System.out.println("t is instanceof Object: " + (t instanceof Object));
}
}

39
J C++ vs. Java
› 2. In Java, membrii grand parent nu sunt direct accesibili

// filename Main.java
class Grandparent {
public void Print() {
System.out.println("Grandparent's Print()");
}
}

class Parent extends Grandparent {


public void Print() {
System.out.println("Parent's Print()");
}
}

40
J C++ vs. Java
class Child extends Parent {
public void Print() {
super.super.Print(); // Trying to access Grandparent's Print()
System.out.println("Child's Print()");
}
} Error:(114, 15) java: <identifier> expected

public class Main {


public static void main(String[] args) {
Child c = new Child();
c.Print();
}
}

41
J C++ vs. Java
› 3. Specificatorul de acces protected nu impiedica alte clase
care nu fac parte din ierarhie sa acceseze membrii
respectivi. Conditia este ca acele clase sa faca parte din
acelasi pachet. In C++ doar clasele derivate pot accesa
membrii privati
// filename B.java
class A {
protected int x = 10, y = 20;
}

class B {
public static void main(String args[]) {
A a = new A();
System.out.println(a.x + " " + a.y);
}
} 42
J C++ vs. Java
› 4. In Java nu exista specificator de acces pentru derivare
› 5. In Java metodele sunt implicit virtuale, in C++ nu
› 6. Java foloseste cuvinte cheie pentru interfata si clase
abstracte

43
J C++ vs. Java
// An abstract class example
abstract class myAbstractClass {
// An abstract method
abstract void myAbstractFun();

// A normal method
void fun() {
System.out.println(“abc");
}
}

public class myClass extends myAbstractClass {


public void myAbstractFun() {
System.out.println(“abc”);
}
}

44
J C++ vs. Java
// An interface example
public interface myInterface {
// myAbstractFun() is public and abstract, even if we don't use these keywords
void myAbstractFun(); // is same as public abstract void myAbstractFun()
}

// Note the implements keyword also.


public class myClass implements myInterface {
public void myAbstractFun() {
System.out.println(“abc”);
}
}

45
J C++ vs. Java
› 7. In Java nu este permisa mostenirea multipla. Totusi o
clasa poate mosteni mai multe interfete
› 8. In C++ exista lista de initializare.
package main;

class Base {
private int b;
Base(int x)
{
b = x;
System.out.println("Base constructor called");
}
}

46
J C++ vs. Java
class Derived extends Base {
private int d;
Derived(int x, int y) {
// Calling parent class parameterized constructor
// Call to parent constructor must be the first line in a Derived class
super(x);
d = y;
System.out.println("Derived constructor called");
}
}

class Main{
public static void main(String[] args) {
Derived obj = new Derived(1, 2);
}
}
Base constructor called
Derived constructor called 47
J C++ vs. Java
› 9. In java nu se pot suprascrie metode private. In C++ da.
class Base {
private void fun() {
System.out.println("Base fun");
}
}

class Derived extends Base {


private void fun() {
System.out.println("Derived fun");
}
public static void main(String[] args) {
Base obj = new Derived();
obj.fun();
}
}
48
#include<iostream>
using namespace std;
J class Derived;

class Base {
private:
virtual void fun() { cout << "Base Fun"; }
friend int main();
};

class Derived: public Base {


public:
void fun() { cout << "Derived Fun"; }
};

int main()
{
Base *ptr = new Derived;
ptr->fun();
return 0;
}
49
J Clase parinte si copil cu acelasi tip de atribute
class Parent
{
int value = 1000;
Parent()
{
System.out.println("Parent Constructor");
}
}

class Child extends Parent


{
int value = 10;
Child()
{
System.out.println("Child Constructor");
}
}
50
J
// Driver class
class Test
{
public static void main(String[] args)
{
Child obj=new Child();
System.out.println(”Reference of Child Type :“ + obj.value);

// Note that doing "Parent par = new Child()"


// would produce same result
Parent par = obj;

// Par holding obj will access the value


// variable of parent class
System.out.println("Reference of Parent Type : “ + par.value);
} Parent Constructor
} Child Constructor
Reference of Child Type : 10 51
Reference of Parent Type : 1000
Swing JComponent Class Diagram

J
J Buffered draw
J Game loop
public class Game implements Runnable
{
J //game attributes

//constructors
public Game() { ... }

private void init() { //initialize the game }

private void update() { ... }

private void draw() { ... }

public void run() { ... }

public synchronized void start() { ... }

public synchronized void stop() { ... }

S-ar putea să vă placă și