UE 2I002 (ex LI230) : éléments de programmation par objets avec Java TD8 - Héritage et liaison dynamique
!!
!
Juliana Silva Bernardes
[email protected]
http://www.lcqb.upmc.fr/julianab/teaching/JAVA/
‣Transtypage d’objet (Cast)
‣instanceof
‣Méthode equals()
‣Liaison dynamique
‣Contexte de méthode
Sumary
Transtypage des types primitifs
‣ Transtypage implicite
‣ On peut affecter à un champ ou une variable d'un type une expression de type moins élevé dans la hiérarchie des types.
int a = 100;
float b = a;
char short int
float
double
long
float a = 100;
int b = a;
‣ Transtypage explicite
‣ Mais nous pouvons pas faire le contraire, sans une Transtypage explicite
TestCast.java:7: error: incompatible types: possible lossy conversion from float to int int b = a;
^
1 error
Transtypage des types primitifs
char short int
float
double
long
float a = 100;
//int b = a;
int b = (int)a;
‣ Transtypage explicite
Transtypage des types primitifs
char short int
float
double
long
float b = 100.87f;
int b = (int)a;
System.out.println(b);
‣ Transtypage explicite
‣ Mais attention on pert en precision
Transtypage des types primitifs
char short int
float double long
100
Dans le terminal
Transtypage d’objet (Cast)
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int x = 2;
int z = 3;
public int getX(){return x;}
public int getZ(){return z;}
}
‣ Transtypage implicite des objets
public class TestCast {
public static void main(String [] args){
A a = new A();
B b = new B();
a = b;
}
} Le plus spécifique peut être attribuer au plus générale
A
B
Transtypage d’objet (Cast)
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int x = 2;
int z = 3;
public int getX(){return x;}
public int getZ(){return z;}
}
public class TestCast {
public static void main(String [] args){
A a = new A();
B b = new B();
b = a;
} }
javac TestCast.java
TestCast.java:5: error: incompatible types: A cannot be converted to B b = a;
^
1 error Juliana
Le plus générale ne peut pas être attribuer au plus spécifique
‣ Transtypage implicite des objets
A
B
Transtypage d’objet (Cast)
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int x = 2;
int z = 3;
public int getX(){return x;}
public int getZ(){return z;}
}
public class TestCast {
public static void main(String [] args){
A a = new A();
A b = new B();
b = a;
System.out.println(b.getX());
} }
$ javac *.java
$ java TestCast
$0
‣ Transtypage implicite des objets
A B
La methode getX() existe dans la class A, pas d’error de compilation
Transtypage d’objet (Cast)
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int w = 2;
int z = 3;
public int getW(){return w;}
public int getZ(){return z;}
}
public class TestCast {
public static void main(String [] args){
A a = new A();
A b = new B();
b = a;
System.out.println(b.getY());
} }
$ javac *.java
$ java TestCast
$ 1
‣ Transtypage implicite des objets
A B
La methode getY() existe dans la class A, pas d’error de compilation
Transtypage d’objet (Cast)
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int w = 2;
int z = 3;
public int getW(){return w;}
public int getZ(){return z;}
}
public class TestCast {
public static void main(String [] args){
A a = new A();
A b = new B();
b = a;
System.out.println(b.getZ());
} }
javac TestCast.java
TestCast.java:6: error: cannot find symbol System.out.println(b.getZ());
^
symbol: method getZ()
location: variable b of type A 1 error
‣ Transtypage implicite des objets
La methode getZ() n'existe pas dans la class A, d’error de compilation
A
B
Transtypage d’objet (Cast)
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int w = 2;
int z = 3;
public int getW(){return w;}
public int getZ(){return z;}
}
public class C extends B { int e = 2;
public int getE(){return e;}
}
public class TestCast {
public static void main(String [] args){
A c = new C();
B b = c;
System.out.println(b.getX());
} }
javac TestCast.java
TestCast.java:4: error: incompatible types: A cannot be converted to B
B b = c;
^
1 error
!
‣ Transtypage implicite des objets
A B C
A
B
C
Transtypage d’objet (Cast)
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int w = 2;
int z = 3;
public int getW(){return w;}
public int getZ(){return z;}
}
public class C extends B { int e = 2;
public int getE(){return e;}
}
public class TestCast {
public static void main(String [] args){
A c = new C();
B b = (B)c;
System.out.print(b.getX());
System.out.println(b.getZ());
} }
‣ Transtypage explicite des objets
$ javac TestCast.java
$ java TestCast
$ 0 4
A
Transtypage d’objet (Cast)
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int w = 2;
int z = 3;
public int getW(){return w;}
public int getZ(){return z;}
}
public class C extends B { int e = 2;
public int getE(){return e;}
}
public class TestCast {
public static void main(String [] args){
A c = new C();
B b = (B)c;
C c2 = (C)c;
System.out.println(b.getX());
System.out.println(c2.getE());
} }
$ javac *.java
$ java TestCast
$ 0 2
‣ Transtypage explicite des objets
A
B
C
Instanceof
Instanceof
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int w = 2;
int z = 3;
public int getW(){return w;}
public int getZ(){return z;}
}
public class C extends A { int e = 2;
public int getE(){return e;}
}
public class TestInstanceOf {
public static void main(String [] args){
A [] tab = new A[10];
for (int i =0; i<tab.length; i++){
if (Math.random() < 0.3){
tab[i] = new B();
}else{
tab[i] = new C();
} }
} }
‣ On veut créer un tableau pour mettre 30% d'objets du type B et 70% du type C
Instanceof
public class TestInstanceOf {
public static void main(String [] args){
A [] tab = new A[10];
for (int i =0; i<tab.length; i++){
if (Math.random() < 0.3) tab[i] = new B();
else
tab[i] = new C();
}
!
for (int i =0; i<tab.length; i++){
A a = tab[i];
if (a instanceof B)
System.out.println(a.getW());
else if (a instanceof C)
System.out.println(a.getE());
‣ Pour les objets du type B, on va imprimer la sortie de la méthode getW(), pour les objets du type C, on va imprimer la sortie de la méthode getE()
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int w = 5;
int z = 3;
public int getW(){return w;}
public int getZ(){return z;}
}
public class C extends A { int e = 2;
public int getE(){return e;}
}
$ javac *.java
TestCast.java:15: error: cannot find symbol System.out.println(a.getW());
^
symbol: method getW()
location: variable a of type A
TestCast.java:17: error: cannot find symbol
Instanceof
public class TestInstanceOf {
public static void main(String [] args){
A [] tab = new A[10];
for (int i =0; i<tab.length; i++){
if (Math.random() < 0.3) tab[i] = new B();
else
tab[i] = new C();
}
for (int i =0; i<tab.length; i++){
A a = tab[i];
if (a instanceof B){
B b = (B) a;
System.out.println(b.getW());
}
else if (a instanceof C){
C c = (C) a;
System.out.println(c.getE());
} }
‣ Pour les objets du type B, on va imprimer la sortie de la méthode getW(), pour les objets du type C, on va imprimer la sortie de la méthode getE()
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int w = 5;
int z = 3;
public int getW(){return w;}
public int getZ(){return z;}
}
public class C extends A { int e = 2;
public int getE(){return e;}
}
Instanceof
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int w = 5;
int z = 3;
public int getW(){return w;}
public int getZ(){return z;}
}
public class C extends A { int e = 2;
public int getE(){return e;}
}
public class TestInstanceOf {
public static void main(String [] args){
A [] tab = new A[10];
for (int i =0; i<tab.length; i++){
if (Math.random() < 0.3) tab[i] = new B();
else
tab[i] = new C();
}
!
for (int i =0; i<tab.length; i++){
A a = tab[i];
if (a instanceof B)
System.out.println(((B)a).getW());
else if (a instanceof C)
System.out.println(((C)a).getE());
‣ Pour les objets du type B, on va imprimer la sortie de la méthode getW(), pour les
objets du type C, on va imprimer la sortie de la méthode getE()
Méthode equals()
Méthode equals()
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int w = 5;
int z = 3;
public int getW(){return w;}
public int getZ(){return z;}
}
public class C extends A { int e = 2;
public int getE(){return e;}
}
public class TestInstanceOf {
public static void main(String [] args){
C c1 = new C();
System.out.print(c1.getE());
C c2 = new C();
System.out.println(c2.getE());
if (c1 == c2)
System.out.println(“égaux");
else
System.out.println(“différents”);
} }
‣ Comment comparer deux objets?
$ javac *.java
$ java TestCast
$ 2 2
Méthode equals()
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int w = 5;
int z = 3;
public int getW(){return w;}
public int getZ(){return z;}
}
public class C extends A { int e = 2;
public int getE(){return e;}
}
public class TestInstanceOf {
public static void main(String [] args){
C c1 = new C();
System.out.print(c1.getE());
C c2 = new C();
System.out.println(c2.getE());
if (c1.equals(c2))
System.out.println(“égaux");
else
System.out.println(“différents”);
} }
‣ Comment comparer deux objets?
$ javac *.java
$ java TestCast
$ 2 2
$ différents
La méthode equals de la class object verifier si les pointeur des objets sont égaux.
Méthode equals()
public class A {
private int x = 0;
private int y = 1;
public int getX(){return x;}
public int getY(){return y;}
}
public class B extends A { int w = 5;
int z = 3;
public int getW(){return w;}
public int getZ(){return z;}
}
public class C extends A { int e = 2;
public int getE(){return e;}
public boolean equals(C c){
return (e == c.e);
} }
public class TestInstanceOf {
public static void main(String [] args){
C c1 = new C();
System.out.print(c1.getE());
C c2 = new C();
System.out.println(c2.getE());
if (c1.equals(c2))
System.out.println(“égaux");
else
System.out.println(“différents”);
} }
‣ Comment comparer deux objets?
$ javac *.java
$ java TestCast
$ 2 2
$ égaux
Liaison dynamique
Liaison dynamique
public class A{
public void faire() {
System.out.println("niveau a");
} }
!
!
public class B extends A { public void faire() {
System.out.println("niveau b");
} }
!
public class C extends B {}
public class QuelleMethode {
public static void main(String[] argv) { A a;
a = new A();
a.faire();
} }
$ javac *.java
$ java QuelleMethode
$ niveau a
La variable a référence un objet de type A ; de toute évidence, la méthode faire utilisée à l'exécution est la méthode faire de la classe A
public class A{
public void faire() {
System.out.println("niveau a");
} }
!
!
public class B extends A { public void faire() {
System.out.println("niveau b");
} }
!
public class C extends B {}
public class QuelleMethode {
public static void main(String[] argv) { A a;
a = new A();
a.faire();
a = new B();
a.faire();
} }
$ javac *.java
Le compilateur regarde le type de la variable a, il s'agit de A, et déciderait donc qu'il s'agit de la méthode faire de la classe A, on obtiendrai niveau a.
Liaison dynamique
public class A{
public void faire() {
System.out.println("niveau a");
} }
!
!
public class B extends A { public void faire() {
System.out.println("niveau b");
} }
!
public class C extends B {}
public class QuelleMethode {
public static void main(String[] argv) { A a;
a = new A();
a.faire();
a = new B();
a.faire();
} }
$ javac *.java
Le compilateur ne peut pas savoir quel objet sera référencé par la variable a à l’exécution.
Le compilateur ne remonte jamais dans l'historique des instructions
Liaison dynamique
public class A{
public void faire() {
System.out.println("niveau a");
} }
!
!
public class B extends A { public void faire() {
System.out.println("niveau b");
} }
!
public class C extends B {}
public class QuelleMethode {
public static void main(String[] argv) { A a;
a = new A();
a.faire();
a = new B();
a.faire();
} }
$ javac *.java
Le compilateur se limite à vérifier que la classe A possède une méthode faire ayant des paramètres correspondant aux paramètres de l'appel
Liaison dynamique
public class A{
public void faire() {
System.out.println("niveau a");
} }
!
!
public class B extends A { public void faire() {
System.out.println("niveau b");
} }
!
public class C extends B {}
public class QuelleMethode {
public static void main(String[] argv) { A a;
a = new A();
a.faire();
a = new B();
a.faire();
} }
La méthode faire à exécuter est décider à l’exécution.
Liaison dynamique
$ javac *.java
$ java QuelleMethode
$ niveau a
$ niveau b
public class A{
public void faire() {
System.out.println("niveau a");
} }
!
!
public class B extends A { public void faire() {
System.out.println("niveau b");
} }
!
public class C extends B {}
public class QuelleMethode {
public static void main(String[] argv) { A a;
a = new A();
a.faire();
a = new B();
a.faire();
a = new C();
a.faire();
} }
L'objet référencé par a est de type C ; la classe C ne redéfinit pas la méthode faire ; la méthode utilisée est alors celle héritée de B.
Liaison dynamique
$ javac *.java
$ java QuelleMethode
$ niveau a
$ niveau b
$ niveau b
Contexte de méthode
Contexte de méthode
public class A {
private int x = 0;
public int j(){return x;}
public int k(){return x;}
}
public class B extends A { int x = 5;
public int j(){return x;}
public int u(){return x;}
}
public class Test {
public static void main(String[] argv) { A a = new A();
B b = new B();
System.out.print(a.j());
!
!
!
!
!
!
!
!
!
!
} }
$ 0
System.out.print(a.k());$ 0
System.out.print(b.j());$ 5
System.out.print(b.u());$ 5
a=bSystem.out.print(a.j());