Académique Documents
Professionnel Documents
Culture Documents
Modélisation et spécification
formelles des logiciels
Hiver 2017
Alexandre Terrasa
Département d’informatique, UQÀM
OCL
Travailler avec les classes
2
Appels statiques
Appeler une méthode statique sur une classe
3
Opération sur les classes
Obtenir l’ensemble de toutes les instances
d’une classe ou interface
Classe.allInstances(): Set(T)
Exemple:
context Etudiant
inv: Etudiant.allInstances()->includes(self)
4
Exercice 6
Tournoi
date: Date tournoi
pro: Boolean
1
tournois *
affronte
équipes matchs *
* *
Joueur Équipe Match
victoire: Boolean
nom: String joueurs équipe nom: String
pro: Boolean
age: Integer
1..5 1 5
*
Exercice 6
Contraintes:
● Deux tournois ne peuvent se dérouler à la
même date
● Deux joueurs du même âge ne peuvent
avoir le même nom
6
Solution 6
context Tournoi
inv: Tournoi.allInstances()->forAll(t1, t2 |
t1 <> t2 implies t1.date <> t2.date)
context Joueur
inv: Joueur.allInstances()->forAll(t1, t2 |
t1 <> t2 and t1.age = t2.age implies
t1.nom <> t2.nom)
7
Opération oclIsNew
Vérifier la création d’une instance
post: object.oclIsNew()
vrai si et seulement si object n’existait pas
dans la pré-condition
post: result.oclIsNew()
8
Rappels sur l’héritage
9
Rappel: héritage
Concept de la programmation orientée objet
● code découpée en classes
● les classes filles héritent des propriétés
de leurs classes mères
Permet
● réutilisation de code
● sous-typage
● polymorphisme
10
Propriétés de l’héritage
La relation d’héritage est
● transitive
● non-réflexive
● non-symétrique
● sans cycle
11
Relation transitive
Si B hérite de A et C hérite de Ovipare
Oiseau
Ainsi
voler()
x
Canard
cancaner()
13
Relation non-symétrique
Si A hérite de B alors B n’hérite pas de A
Oiseau
voler()
● Tous les canards sont
des oiseaux
x ● Tous les oiseaux ne
sont pas forcément des
Canard
canards
cancaner()
14
Relation sans cycle
Si B hérite de A et C hérite Ovipare
hériter de C
Oiseau
x voler()
Canard
cancaner()
15
Principe de substitution de
Liskov
- B. Liskov et J. Wing
Family Values: A Behavioral Notion of Subtyping, 1993
16
Exemple de substitualité
Arme
Guerrier
équiper(Arme arme)
Épée Hache
17
Exemple de substitualité
class Guerrier {
void équiper(Arme arme) { /* … */ }
}
18
Spécialisation et redéfinition
Une classe
● hérite des propriétés des classes qu’elle
spécialise
● peut étendre ses super-classes en
○ ajoutant de nouvelles propriétés
○ redéfinissant les propriétés héritées
19
Sous-typage
Une classe = Un type (mais pas toujours)
● définition des types de données
● utilisation dans les signatures
Type et héritage
● Si B hérite de A, alors B est un sous-type
de A
● sous-typage = mêmes principes que la
relation d’héritage 20
Restrictions du principe de Liskov
21
Héritage et variance des types
Idée
● changer le type des Animal
arguments et des types de
manger(n: Nourriture)
retour dans les
redéfinitions
Vache
manger(n: TYPE?)
Questions
● est-ce possible?
● selon quelles contraintes? 22
Notion de variance
Mangeable
Soit n: T avec T = Nourriture
● T varie dans le même sens
que la hiérarchie des types
○ T = Herbe Nourriture
○ Covariance
● T varie dans le sens inverse
de la hiérarchie des types
○ T = Mangeable Herbe
○ Contravariance
23
Variance des arguments
manger(n: Nourriture)
Vache Herbe
manger(n: Herbe) 25
Exemple de la vache folle
Pourquoi la redéfinition
covariante des arguments est
non-sûre?
Animal Nourriture
manger(n: Nourriture)
Vache Herbe
manger(n: Herbe) 26
Exemple de la vache folle
Vache v = new Vache()
v.manger(new Herbe()) // OK
v.manger(new Vache()) // Refusé
27
Exemple de la vache folle
Vache v = new Vache()
v.manger(new Herbe()) // OK
v.manger(new Vache()) // Refusé
28
Variance du type de retour
Règle pour un typage sûr
● Redéfinition covariante des types de
retour des méthodes
Exemples: C++, Java, Scala, D, Eiffel
Note: l’invariance marche aussi…
Exemple: C#
29
Exemple du distributeur
Pourquoi la redéfinition contravariante des
types de retour est-elle non-sûre?
Distributeur Nourriture
distribuer: Herbe
d = new Distributeur2()
v.manger(d.distribuer())
// La vache mange autre chose que de l’herbe
31
Variance des attributs
Pour un attribut foo: T
● setFoo(foo: T)
○ contravariance des types des arguments
● getFoo(): T
○ covariance des types de retour
Exemples: https://github.com/Morriar/INF3143_variance 33
OCL
Typage
34
Types OCL primitifs
Boolean true, false
Integer 1 ; -3 ; 12 ; 42
Real 1,5 ; 3,14 ; -10.3
String ‘Hello World!’
OCLVoid null ; invalid
35
Collections
OCL définit 4 types de collections
● Set
● OrderedSet
● Bag
● Séquence
37
Propagation des invalides
Une valeur invalide se propage dans toute
l’expression sauf exception:
● true or invalid = true
● false and invalid = false
● false implies invalid = true
● invalid implies true = true
38
Type d’un objet
Vérifier le type dynamique d’un objet
● exactement du type Type
object.oclIsTypeOf(Type)
● un sous-type du type Type
object.oclIsKindOf(Type)
39
Transtypage
Changer le type statique d’un objet
object.oclAsType(Type2)
41
Transtypage et collections
Changer le type statique d’une collection
collection->oclAsType(Set(String))
Changer le type statique des éléments
collection->collect(oclAsType(String))
Sélectionner les éléments d’un certain type
collection->selectByKind(Etudiant)
42
Principe de substitution
Tout ce qui s’applique à un animal s’applique
aussi à une vache.
44
Substitution et conditions
Principe de substitution sur les conditions
● les pré-conditions peuvent seulement être
assouplies (contravariance)
● les post-conditions peuvent seulement
être renforcées (covariance)
45
Exemple
Pré-condition covariante invalide
L’exemple est invalide, expliquez pourquoi?
pre: nourriture.oclIsKindOf(Nourriture)
pre: nourriture.oclIsKindOf(Herbe)
46
Solution
List<Animaux> arche = new ArrayList<Animal>();
arche.add(new Vache()) // Vache <: Animal, OK
nourrir_au_grain(arche)
47
Conclusion
OCL
● Permet d’accéder aux instances d’une
classe
○ allInstances()
● Permet de travailler avec les types du
modèle
○ oclIsTypeOf(), oclIsKindOf(), oclAsKindOf()
49