premiere version stable du cours de poo
This commit is contained in:
parent
86e9646de9
commit
b73e7c85ff
|
@ -0,0 +1,260 @@
|
||||||
|
Ojets en python
|
||||||
|
=================
|
||||||
|
|
||||||
|
un object est une entité possédant une identité, un état, et un comportement.
|
||||||
|
|
||||||
|
Un object correspondant généralement à une entité du monde réel, mais
|
||||||
|
cette entité peut être abstraite.
|
||||||
|
|
||||||
|
On parle aussi d'instance.
|
||||||
|
|
||||||
|
.. glossary::
|
||||||
|
|
||||||
|
état d'un objet
|
||||||
|
ensemble de propriétés auxquelles sont associées des
|
||||||
|
valeurs.
|
||||||
|
|
||||||
|
Les variables de l'objet sont appelées des attributs.
|
||||||
|
le comportement d'un objet :
|
||||||
|
|
||||||
|
- des actions effectuées sur l'objet
|
||||||
|
- des demandes de services faites à l'objet
|
||||||
|
|
||||||
|
des envois de messages à l'objet = appel de méthodes
|
||||||
|
|
||||||
|
classes d'objets
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
encapsulation (cacher les attributs (variables d'état)) d'un objet).
|
||||||
|
interfaces : chaque aspect d'une classe peut être vu comme une interface.
|
||||||
|
Une interface décrit un ensemble de comportements.
|
||||||
|
on peut considérer une interface comme un protocole d'utilisation d'un objet
|
||||||
|
dans un contexte donné.
|
||||||
|
|
||||||
|
on peut alors créer des outils qui sauront traiter n'importe quel objet
|
||||||
|
pourvu qu'il respecte une ensemble d'interfaces.
|
||||||
|
|
||||||
|
héritage (est une sorte de)
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
Polymorphisme (un objet apparait comme une instance d'une classe parente)
|
||||||
|
(exemple un courrier (postal, colis, lettre) est représenté par une classe
|
||||||
|
abstraite ``Pli``::
|
||||||
|
|
||||||
|
class Pli:
|
||||||
|
get_prix(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
class Lettre(Pli):
|
||||||
|
get_prix(self):
|
||||||
|
return 3
|
||||||
|
|
||||||
|
class Colis(Pli):
|
||||||
|
get_prix(self):
|
||||||
|
return 10
|
||||||
|
|
||||||
|
def genere_facture(pli):
|
||||||
|
return "prix : {0}".format(pli.get_prix())
|
||||||
|
|
||||||
|
la méthode ``get_prix`` selar appelée indépendamment du type de l'objet.
|
||||||
|
|
||||||
|
Méthode de modélisation (UML), réutilisation de code.
|
||||||
|
Mise en oeuvre de design patterns en python.
|
||||||
|
|
||||||
|
introspection
|
||||||
|
--------------
|
||||||
|
|
||||||
|
- L’introspection est la possibilité d’avoir des informations sur l’objet lors de l’exécution.
|
||||||
|
- `type(obj)` renvoie le type de l’objet.
|
||||||
|
- La fonction `dir(obj)` qui renvoie la liste des attributs et méthodes.
|
||||||
|
- Le module inspect contient plusieurs fonctions qui permettent d’avoir des informations sur les objets.
|
||||||
|
|
||||||
|
- la méthode `vars(obj)` renvoie les noms et les valeurs d’un objet sous forme de
|
||||||
|
dictionnaire.
|
||||||
|
- la méthode `obj.__class__` renvoie la classe à laquelle appartient l’objet
|
||||||
|
- La fonction getattr renvoie la valeur associée à l’attribut
|
||||||
|
- La fonction setattr est équivalente à obj.att = v.
|
||||||
|
- La fonction isinstance(obj, class) renvoie True si obj est une instance de class et
|
||||||
|
renvoie False sinon.
|
||||||
|
|
||||||
|
définition et syntaxe
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Une classe est la définition d’un nouveau type utilisateur.
|
||||||
|
Ce type de variable rassemble plusieurs données : attributs et définit des
|
||||||
|
fonctions : méthodes.
|
||||||
|
|
||||||
|
- Un objet est une instance d’une classe.
|
||||||
|
(classe <=> Type, objet <=> variable).
|
||||||
|
|
||||||
|
- Syntaxe:
|
||||||
|
|
||||||
|
Création une classe:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
>>> class Vehicule:
|
||||||
|
pass
|
||||||
|
Création d’un objet de type Vehicule:
|
||||||
|
>>> mon_vehicule = Vehicule()
|
||||||
|
|
||||||
|
attributs et méthodes
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
- Les attributs permettent de stocker les informations au niveau de la classe.
|
||||||
|
- Les méthodes sont des fonctions définies dans une classe.
|
||||||
|
- Syntaxe:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
>>> class Vehicule:
|
||||||
|
def __init__(self):
|
||||||
|
self.couleur = ''
|
||||||
|
self.vitesse = 0
|
||||||
|
def avancer(self):
|
||||||
|
self.vitesse = self.vitesse + 1
|
||||||
|
|
||||||
|
Les méthodes "__init__" et " __new__"
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
- La méthode `__init__` est une méthode qui est appelée automatiquement après
|
||||||
|
la création de l’objet.
|
||||||
|
|
||||||
|
- La méthode `__init__` permet d’initialiser les attributs, ce n’est pas le
|
||||||
|
constructeur, c’est `__new__` qui crée l’instance.
|
||||||
|
|
||||||
|
Premier argument d’une méthode
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Le premier paramètre d’une méthode est une référence vers l’instance, on
|
||||||
|
l’appelle **self** par convention.
|
||||||
|
|
||||||
|
.. ifconfig: exercice
|
||||||
|
|
||||||
|
Définir une classe Étudiant qui a comme
|
||||||
|
attributs: nom, prenom et age et qui a
|
||||||
|
comme méthode Infos() qui affiche le nom,
|
||||||
|
le prénom et l’âge de l’étudiant comme suit:
|
||||||
|
nom: [Prenom]
|
||||||
|
prenom: [NOM]
|
||||||
|
Age: [age]
|
||||||
|
|
||||||
|
attributs et méthodes privés
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
- En python, tout est publc. Toutes les méthodes et attributs sont
|
||||||
|
accessibles de l’extérieur de la classe et peuvent être modifiés.
|
||||||
|
|
||||||
|
- Un membre (attribut ou méthode) est considéré public si n’est pas précédé
|
||||||
|
d’underscore.
|
||||||
|
- Si le membre est précédé par un seul underscore il est considéré comme
|
||||||
|
protégé.
|
||||||
|
- Si le membre est précédé par deux underscores et qui se termine au plus par
|
||||||
|
un underscore, il est considéré comme "méthode spéciale".
|
||||||
|
|
||||||
|
|
||||||
|
attributs de classe et d’instance
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
- Les attributs de classe sont accessibles sans avoir à créer une instance
|
||||||
|
de cette classe. Ce sont des variables appartenant à la classe elle-même.
|
||||||
|
- Les attributs d’instance sont accessibles après la création d’un objet. Ces
|
||||||
|
attributs sont conventionnellement créés dans la méthode __init__(self).
|
||||||
|
- Exemple:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
>>> class Vehicule:
|
||||||
|
nom = ''
|
||||||
|
def __init__(self):
|
||||||
|
self.couleur = ''
|
||||||
|
|
||||||
|
L’attribut **nom** est un attribut de classe et l’attribut ‘couleur’ est un
|
||||||
|
attribut d’instance.
|
||||||
|
|
||||||
|
On peut ajouter des attributs d’instance après la création de l’instance.
|
||||||
|
|
||||||
|
|
||||||
|
>>> mon_vehicule.etat = 'bon'
|
||||||
|
|
||||||
|
héritage simple
|
||||||
|
---------------
|
||||||
|
|
||||||
|
- L’héritage consiste à créer une classe dite classe fille à partir d’une autre
|
||||||
|
classe dite classe mère.
|
||||||
|
- Soit B une classe qui hérite d’une classe mère A
|
||||||
|
- B hérite tous les attributs et méthodes de la classe A.
|
||||||
|
- B peut avoir d’autres attributs et méthodes.
|
||||||
|
- Quelques méthodes peuvent être redéfinies dans la classe B.
|
||||||
|
- Les classes B et A sont reliées par la relation ‘est-un’ ( B est un A).
|
||||||
|
|
||||||
|
Syntaxe :
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
class B(A)
|
||||||
|
- Exemple:
|
||||||
|
>>> class Vehicule:
|
||||||
|
def __init__(self):
|
||||||
|
self.couleur = ''
|
||||||
|
self.vitesse = 0
|
||||||
|
>>> class Voiture(Vehicule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
surcharge d’attributs et de méthodes
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
Surcharger un attribut est le fait de redéfinir sa valeur dans la classe
|
||||||
|
fille.
|
||||||
|
La surcharge d’une méthode est la modification de son comportement. Il
|
||||||
|
suffit alors de redéfinir la méthode au sein de la classe. comment
|
||||||
|
appeler la méthode de la classe parente ?
|
||||||
|
Exemple:
|
||||||
|
|
||||||
|
Redéfinition de la méthode __init__:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
>>> class Rectangle(object):
|
||||||
|
def __init__(self, a, b):
|
||||||
|
self.long = a
|
||||||
|
self.larg = b
|
||||||
|
>>> class Carre(Rectangle):
|
||||||
|
def __init__ (self, a):
|
||||||
|
self.long = a
|
||||||
|
self.larg = a
|
||||||
|
|
||||||
|
La méthode __init__ de la classe ‘Rectangle’ n’est appelée que si on
|
||||||
|
utilise la fonction super : super(Carre, self).__init__(a,a) appelle
|
||||||
|
automatiquement la méthode de la classe mère.
|
||||||
|
Exemple :
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
>>> class carre(Rectangle):
|
||||||
|
def __init__(self, a):
|
||||||
|
super().__init__(a, a)
|
||||||
|
|
||||||
|
|
||||||
|
héritage vs. composition
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
- L’héritage lie deux objets par une relation de type «est-un» alors que
|
||||||
|
la composition lie deux objets par une relation de type «a-un»
|
||||||
|
|
||||||
|
- Exemple:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
|
||||||
|
>>> class Moteur:
|
||||||
|
pass
|
||||||
|
>>> class MoteurElectrique(Moteur):
|
||||||
|
pass
|
||||||
|
>>> class Voiture:
|
||||||
|
moteur = Moteur()
|
||||||
|
|
||||||
|
La classe MoteurElectrique est un Moteur (héritage).
|
||||||
|
La classe Voiture a un moteur (Composition).
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
``cli`` : command line interpreter
|
||||||
|
===================================
|
||||||
|
|
||||||
|
As Catherine Devlin, the author of `cmd2 <https://pythonhosted.org/cmd2/>`_ explained it:
|
||||||
|
|
||||||
|
| Slightly after the bronze age came the command line interpreter.
|
||||||
|
| I'm talking about **command line interpreters**
|
||||||
|
| that is somewhat more specific terms than **command line applications**
|
||||||
|
| or **command line utilities**
|
||||||
|
|
||||||
|
A command line interpreter is a program that is
|
||||||
|
|
||||||
|
- plain text
|
||||||
|
- gives you a prompt
|
||||||
|
- it gets all of its input at once
|
||||||
|
- produces his output usually as text lines
|
||||||
|
- gives you a prompt again
|
||||||
|
|
||||||
|
unix shell instructions are a good example of that.
|
||||||
|
A command line utilities is a unix-like program that gets all of its inputs at once
|
||||||
|
and gives a result at once.
|
||||||
|
|
||||||
|
At the other side, a text user interface is a litlle bit like a gui, it's closer to a gui.
|
||||||
|
at this time, you have to think of how much effort your interface is worth,
|
||||||
|
|
||||||
|
| otherwise it's gonna kill you to write it (Catherine Devlin)
|
||||||
|
|
||||||
|
Basic cli functionnalities
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
A complete command line interpreter written with ``cmd``
|
||||||
|
|
||||||
|
- it recognizes the concept of help (contextual help)
|
||||||
|
- the previous commands (history) can be called again with the keyboard's up and down arrows
|
||||||
|
- if yout hit Ctr-R and the first letters of a command you can call it again
|
||||||
|
(bash-style history)
|
||||||
|
- the tab key will finish out your command
|
||||||
|
|
||||||
|
how to use it
|
||||||
|
--------------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
>>> from cli import Cli
|
||||||
|
>>> prompt = Cli()
|
||||||
|
>>> prompt.cmdloop()
|
||||||
|
cli (command line interpreter)
|
||||||
|
(type help or ? for commands list)
|
||||||
|
#Prompt> ?
|
||||||
|
|
||||||
|
Documented commands (type help <command>):
|
||||||
|
==========================================
|
||||||
|
EOF exit
|
||||||
|
|
||||||
|
Undocumented commands:
|
||||||
|
======================
|
||||||
|
cmd help quit
|
||||||
|
|
||||||
|
#Prompt>
|
||||||
|
|
||||||
|
to add a command, just use inheritance::
|
||||||
|
|
||||||
|
|
||||||
|
>>> from cli import Cli
|
||||||
|
>>> class Prompt(Cli):
|
||||||
|
... def do_hello(self, line):
|
||||||
|
... print "hello %s", line
|
||||||
|
...
|
||||||
|
>>> prompt = Prompt()
|
||||||
|
>>> prompt.cmdloop()
|
||||||
|
cli (command line interpreter)
|
||||||
|
(type help or ? for commands list)
|
||||||
|
#Prompt> ?
|
||||||
|
|
||||||
|
Documented commands (type help <command>):
|
||||||
|
==========================================
|
||||||
|
EOF exit
|
||||||
|
|
||||||
|
Undocumented commands:
|
||||||
|
======================
|
||||||
|
cmd hello help quit
|
||||||
|
|
||||||
|
#Prompt> hello world
|
||||||
|
|
||||||
|
|
||||||
|
.. glossary::
|
||||||
|
|
||||||
|
CLI
|
||||||
|
CLI stands for Command Line Interface, is a tool that, well, it gives you a prompt
|
||||||
|
|
||||||
|
.. literalinclude:: ../snippets/cli.py
|
||||||
|
:caption: basic command line utility library
|
||||||
|
|
||||||
|
If you want your :term:`cli` to have more functionalities, try `cm2 <http://www.phyast.pitt.edu/~micheles/python/cmd2.html>`_.
|
||||||
|
|
||||||
|
.. important:: Don't use `input()` but `raw_input()` for your command lines
|
|
@ -4,6 +4,11 @@ Annexes
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
ojbML
|
||||||
|
ConstructionParFermeture
|
||||||
|
cli
|
||||||
|
symbol
|
||||||
|
wrapper
|
||||||
surete
|
surete
|
||||||
agile
|
agile
|
||||||
scrum
|
scrum
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
Object en ocaml
|
||||||
|
===============
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
|
||||||
|
utop # let myPt =
|
||||||
|
object
|
||||||
|
val mutable x = 0
|
||||||
|
val mutable y = 0
|
||||||
|
method get_x = x
|
||||||
|
method get_y = y
|
||||||
|
method setcoord new_x new_y = x <- new_x ; y<- new_y
|
||||||
|
end;;
|
||||||
|
val myPt : < get_x : int; get_y : int; setcoord : int -> int -> unit > = <obj> ─( 17:23:21 )─< command 1 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─utop # myPt#get_x ;;
|
||||||
|
- : int = 0 ─( 17:23:24 )─< command 2 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─utop # myPt#setcoord 5 89 ;;
|
||||||
|
- : unit = () ─( 17:23:45 )─< command 3 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─utop # myPt#get_y
|
||||||
|
;;
|
||||||
|
- : int = 89
|
||||||
|
|
||||||
|
|
||||||
|
classe point
|
||||||
|
------------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
|
||||||
|
(* ocamlg points.cmo pointClass.ml *)
|
||||||
|
open Graphics ;;
|
||||||
|
open Points ;;
|
||||||
|
open_graph " ";;
|
||||||
|
set_line_width 5 ;;
|
||||||
|
set_color magenta ;;
|
||||||
|
|
||||||
|
set_window_title "points" ;;
|
||||||
|
|
||||||
|
let p1 = new point (0,0)
|
||||||
|
let p2 = new point (3,4) ;;
|
||||||
|
p1#lineto (10,28) ;;
|
||||||
|
p1#lineto (222,55) ;;
|
||||||
|
print_string (p1#to_string ()) ;;
|
||||||
|
print_newline () ;;
|
||||||
|
|
||||||
|
p1#lineto (50, 125) ;;
|
||||||
|
|
||||||
|
ignore (read_key () ) ;;
|
||||||
|
close_graph () ;;
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
|
||||||
|
(* l'objet point comme la possibilite de lier
|
||||||
|
la representation et le dessin sur le graphe
|
||||||
|
*)
|
||||||
|
(* ocamlc graphics.cma points.ml *)
|
||||||
|
class point (x_init,y_init) =
|
||||||
|
object
|
||||||
|
val mutable x = x_init
|
||||||
|
val mutable y = y_init
|
||||||
|
method get_x = x
|
||||||
|
method get_y = y
|
||||||
|
method moveto (a,b) = x <- a ; y <- b
|
||||||
|
method rmoveto (dx,dy) = x <- x + dx ; y <- y + dy
|
||||||
|
method lineto (a, b) = Graphics.lineto a b ; x <- a ; y <- b
|
||||||
|
method to_string () =
|
||||||
|
"( " ^ (string_of_int x) ^ ", " ^ (string_of_int y) ^")"
|
||||||
|
method distance () = sqrt (float(x*x + y*y))
|
||||||
|
end ;;
|
||||||
|
|
||||||
|
(*
|
||||||
|
let p1 = new point (0,0)
|
||||||
|
let p2 = new point (3,4) ;;
|
||||||
|
p1#get_x;;
|
||||||
|
p2#get_y;;
|
||||||
|
p1#to_string();;
|
||||||
|
p1#moveto (1,2) ;;
|
||||||
|
p1#rmoveto (2,5) ;;
|
||||||
|
p1#to_string () ;;
|
||||||
|
*)
|
||||||
|
|
||||||
|
(* point avec un record
|
||||||
|
|
||||||
|
type color = Rouge | Vert | Bleu
|
||||||
|
type point = {x:int; c:color}
|
||||||
|
|
||||||
|
class point (x_init, y_init) =
|
||||||
|
object
|
||||||
|
val x = x_init
|
||||||
|
val y = y_init
|
||||||
|
method get_x = x
|
||||||
|
method get_y = y
|
||||||
|
(* a faire avec le self *)
|
||||||
|
method moveto (point:p) = point(p.get_a,p.get_b)
|
||||||
|
method rmoveto (point:p) = point(x + dx, y + dy)
|
||||||
|
method to_string () =
|
||||||
|
"( " ^ (string_of_int x) ^ ", " ^ (string_of_int y) ^")"
|
||||||
|
method distance () = sqrt (float(x*x + y*y))
|
||||||
|
end ;;
|
||||||
|
|
||||||
|
let p1 = new point (0, 0);;
|
||||||
|
let p2 = new point (3, 4);;
|
||||||
|
(*
|
||||||
|
p1#get_x;;
|
||||||
|
p2#get_y;;
|
||||||
|
p1#to_string();;
|
||||||
|
*)
|
|
@ -0,0 +1,153 @@
|
||||||
|
Symbols
|
||||||
|
=======
|
||||||
|
|
||||||
|
Using sets
|
||||||
|
-----------
|
||||||
|
|
||||||
|
There are different ways of defining symbols.
|
||||||
|
You can do it very simply with sets::
|
||||||
|
|
||||||
|
>>> s = set("abc", "def", "ghi")
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "<stdin>", line 1, in <module>
|
||||||
|
TypeError: set expected at most 1 arguments, got 3
|
||||||
|
>>> s = set(["abc", "def", "ghi"])
|
||||||
|
>>> s
|
||||||
|
set(['abc', 'ghi', 'def'])
|
||||||
|
>>> "abc" in s
|
||||||
|
True
|
||||||
|
>>>
|
||||||
|
|
||||||
|
|
||||||
|
If you are using python 3.X, the notation::
|
||||||
|
|
||||||
|
Python 3.5.2 (default, Sep 10 2016, 08:21:44)
|
||||||
|
[GCC 5.4.0 20160609] on linux
|
||||||
|
Type "help", "copyright", "credits" or "license" for more information.
|
||||||
|
>>> 1 in {1,2,3}
|
||||||
|
True
|
||||||
|
>>>
|
||||||
|
|
||||||
|
is very effective for working with symbols.
|
||||||
|
Use immutable sets.
|
||||||
|
|
||||||
|
Using namespaces
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Here is a real world example from the tiramisu library
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# ____________________________________________________________
|
||||||
|
class _NameSpace(object):
|
||||||
|
"""convenient class that emulates a module
|
||||||
|
and builds constants (that is, unique names)
|
||||||
|
when attribute is added, we cannot delete it
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __setattr__(self, name, value):
|
||||||
|
if name in self.__dict__: # pragma: optional cover
|
||||||
|
raise ConstError(_("can't rebind {0}").format(name))
|
||||||
|
self.__dict__[name] = value
|
||||||
|
|
||||||
|
def __delattr__(self, name): # pragma: optional cover
|
||||||
|
if name in self.__dict__:
|
||||||
|
raise ConstError(_("can't unbind {0}").format(name))
|
||||||
|
raise ValueError(name)
|
||||||
|
|
||||||
|
|
||||||
|
class GroupModule(_NameSpace):
|
||||||
|
"emulates a module to manage unique group (OptionDescription) names"
|
||||||
|
class GroupType(str):
|
||||||
|
"""allowed normal group (OptionDescription) names
|
||||||
|
*normal* means : groups that are not master
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
class DefaultGroupType(GroupType):
|
||||||
|
"""groups that are default (typically 'default')"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MasterGroupType(GroupType):
|
||||||
|
"""allowed normal group (OptionDescription) names
|
||||||
|
*master* means : groups that have the 'master' attribute set
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class OwnerModule(_NameSpace):
|
||||||
|
"""emulates a module to manage unique owner names.
|
||||||
|
|
||||||
|
owners are living in `Config._cfgimpl_value_owners`
|
||||||
|
"""
|
||||||
|
class Owner(str):
|
||||||
|
"""allowed owner names
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
class DefaultOwner(Owner):
|
||||||
|
"""groups that are default (typically 'default')"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MultiTypeModule(_NameSpace):
|
||||||
|
"namespace for the master/slaves"
|
||||||
|
class MultiType(str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class DefaultMultiType(MultiType):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MasterMultiType(MultiType):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class SlaveMultiType(MultiType):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# ____________________________________________________________
|
||||||
|
def populate_groups():
|
||||||
|
"""populates the available groups in the appropriate namespaces
|
||||||
|
|
||||||
|
groups.default
|
||||||
|
default group set when creating a new optiondescription
|
||||||
|
|
||||||
|
groups.master
|
||||||
|
master group is a special optiondescription, all suboptions should be
|
||||||
|
multi option and all values should have same length, to find master's
|
||||||
|
option, the optiondescription's name should be same than de master's
|
||||||
|
option
|
||||||
|
|
||||||
|
groups.family
|
||||||
|
example of group, no special behavior with this group's type
|
||||||
|
"""
|
||||||
|
groups.default = groups.DefaultGroupType('default')
|
||||||
|
groups.master = groups.MasterGroupType('master')
|
||||||
|
groups.family = groups.GroupType('family')
|
||||||
|
|
||||||
|
|
||||||
|
def populate_owners():
|
||||||
|
"""populates the available owners in the appropriate namespaces
|
||||||
|
|
||||||
|
default
|
||||||
|
is the config owner after init time
|
||||||
|
|
||||||
|
user
|
||||||
|
is the generic is the generic owner
|
||||||
|
"""
|
||||||
|
setattr(owners, 'default', owners.DefaultOwner('default'))
|
||||||
|
setattr(owners, 'user', owners.Owner('user'))
|
||||||
|
|
||||||
|
def addowner(name):
|
||||||
|
"""
|
||||||
|
:param name: the name of the new owner
|
||||||
|
"""
|
||||||
|
setattr(owners, name, owners.Owner(name))
|
||||||
|
setattr(owners, 'addowner', addowner)
|
||||||
|
|
||||||
|
# ____________________________________________________________
|
||||||
|
# populate groups and owners with default attributes
|
||||||
|
groups = GroupModule()
|
||||||
|
populate_groups()
|
||||||
|
owners = OwnerModule()
|
||||||
|
populate_owners()
|
|
@ -0,0 +1,53 @@
|
||||||
|
Wrapping
|
||||||
|
=========
|
||||||
|
|
||||||
|
|
||||||
|
a wrapper can restrict, heritage cannot.
|
||||||
|
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
|
||||||
|
# ____________________________________________________________
|
||||||
|
# Base objects
|
||||||
|
|
||||||
|
class Element:
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<Element %s>"% self.name
|
||||||
|
|
||||||
|
# ____________________________________________________________
|
||||||
|
# Wrapped objects
|
||||||
|
|
||||||
|
class W_Element:
|
||||||
|
def __init__(self, name, wrap):
|
||||||
|
self._name = "wrapped_element" or name
|
||||||
|
self._w = wrap
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
return getattr(self._w, name)
|
||||||
|
|
||||||
|
def get_w(self, name):
|
||||||
|
return getattr(self._w, name)
|
||||||
|
|
||||||
|
def set_w(self, name, value):
|
||||||
|
return setattr(self._w, name, value)
|
||||||
|
|
||||||
|
_w = property (get_w, set_w)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "[W_Element %s]"% repr(self._name)
|
||||||
|
|
||||||
|
# ____________________________________________________________
|
||||||
|
# tests
|
||||||
|
|
||||||
|
e = Element('element 1')
|
||||||
|
w_e = W_Element('w_element 1', e)
|
||||||
|
e.a = 2
|
||||||
|
print w_e.a
|
||||||
|
print w_e
|
||||||
|
w_e.b = 5
|
||||||
|
print w_e.b
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
let rec fact = function
|
|
||||||
|1 -> 1
|
|
||||||
| n -> n * fact (n-1) ;;
|
|
||||||
|
|
||||||
let print_fact n =
|
|
||||||
Printf.printf "factorielle %i = %i\n" n (fact n)
|
|
||||||
|
|
||||||
let main () =
|
|
||||||
begin
|
|
||||||
print_fact 5 ;
|
|
||||||
print_newline () ;
|
|
||||||
exit 0 ;
|
|
||||||
end
|
|
||||||
|
|
||||||
let _ = main ()
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
def factorielle(n):
|
|
||||||
if (n > 1):
|
|
||||||
r = n*factorielle(n-1)
|
|
||||||
else:
|
|
||||||
r = 1
|
|
||||||
return r
|
|
||||||
|
|
||||||
def print_fact(n):
|
|
||||||
print "factorielle {} = {}\n".format(5, factorielle(5))
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
print_fact(5)
|
|
|
@ -56,7 +56,7 @@ source_suffix = '.txt'
|
||||||
master_doc = 'index'
|
master_doc = 'index'
|
||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'Algorithmique Approfondie'
|
project = u'POO'
|
||||||
copyright = u'2017, Gwen'
|
copyright = u'2017, Gwen'
|
||||||
author = u'Gwen'
|
author = u'Gwen'
|
||||||
|
|
||||||
|
@ -239,7 +239,7 @@ latex_elements = {
|
||||||
# (source start file, target name, title,
|
# (source start file, target name, title,
|
||||||
# author, documentclass [howto, manual, or own class]).
|
# author, documentclass [howto, manual, or own class]).
|
||||||
latex_documents = [
|
latex_documents = [
|
||||||
(master_doc, 'ProgrammationOrienteeObjet.tex', u'Cours de programmation orientée objet',
|
(master_doc, 'ProgrammationOrienteeObjet.tex', u'Démarches objet',
|
||||||
u'INFAL26', 'manual'),
|
u'INFAL26', 'manual'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ latex_use_parts = False
|
||||||
# One entry per manual page. List of tuples
|
# One entry per manual page. List of tuples
|
||||||
# (source start file, name, description, authors, manual section).
|
# (source start file, name, description, authors, manual section).
|
||||||
man_pages = [
|
man_pages = [
|
||||||
(master_doc, 'algorithmique', u'Algorithmique Documentation',
|
(master_doc, 'algorithmique', u'Démarches objet',
|
||||||
[author], 1)
|
[author], 1)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -283,8 +283,8 @@ man_pages = [
|
||||||
# (source start file, target name, title, author,
|
# (source start file, target name, title, author,
|
||||||
# dir menu entry, description, category)
|
# dir menu entry, description, category)
|
||||||
texinfo_documents = [
|
texinfo_documents = [
|
||||||
(master_doc, 'Algorithmique', u'Algorithmique Documentation',
|
(master_doc, 'Démarches objet', u'Démarches objet',
|
||||||
author, 'Algorithmique', 'One line description of project.',
|
author, 'Démarches objet', 'One line description of project.',
|
||||||
'Miscellaneous'),
|
'Miscellaneous'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
Définitions
|
||||||
|
===========
|
||||||
|
|
||||||
|
Protocole à méta-objets
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Principes ouverts, principes fermés.
|
||||||
|
|
||||||
|
exemple : les slots en python
|
||||||
|
|
||||||
|
|
||||||
|
expliquer le for en python : c'est parce que l'objet possède une méthode
|
||||||
|
__iter__
|
||||||
|
|
||||||
|
|
||||||
|
un objet avec des slots utilise moins de mémoire qu'un dict.
|
||||||
|
sinon, il en utilise plus
|
||||||
|
|
||||||
|
Termes
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. glossary::
|
||||||
|
|
||||||
|
Abstraction
|
||||||
|
|
||||||
|
The details of the implementation are hidden in the object, and the external interface is just the set of publicly accessible methods.
|
||||||
|
|
||||||
|
Dynamic lookup
|
||||||
|
|
||||||
|
When a message is sent to an object, the method to be executed is determined by the implementation of the object, not by some static property of the program. In other words, different objects may react to the same message in different ways.
|
||||||
|
|
||||||
|
Subtyping
|
||||||
|
|
||||||
|
If an object a has all the functionality of an object b, then we may use a in any context where b is expected.
|
||||||
|
|
||||||
|
Inheritance
|
||||||
|
|
||||||
|
The definition of one kind of object can be reused to produce a new kind of object. This new definition can override some behavior, but also share code with its parent.
|
||||||
|
|
||||||
|
Open recursion
|
||||||
|
|
||||||
|
An object's methods can invoke another method in the same object using a special variable (often called self or this). When objects are created from classes, these calls use dynamic lookup, allowing a method defined in one class to invoke methods defined in another class that inherits from the first.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
objet en python
|
||||||
|
|
||||||
|
>>> o = object()
|
||||||
|
>>> o.a = 1
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "<stdin>", line 1, in <module>
|
||||||
|
AttributeError: 'object' object has no attribute 'a'
|
||||||
|
>>>
|
||||||
|
|
||||||
|
l'objet est l'objet de base, tous les autres objets héritent de cet objet
|
||||||
|
>>> class A: pass
|
||||||
|
...
|
||||||
|
>>> isinstance(A, object)
|
||||||
|
True
|
||||||
|
>>>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Five are structural:
|
||||||
|
|
||||||
|
Abstraction Representing reality in a simplified form by removing certain distinctions so that we can see the commonalities.
|
||||||
|
Class A generalised description of similar objects that share a common structure and behaviour.
|
||||||
|
Encapsulation Data and behaviour are defined within an object and separated from everything else, protecting the internal representation of the object.
|
||||||
|
Inheritance Allows the attributes and methods of one class to be based on another existing class.
|
||||||
|
Object An individual, identifiable item, either real or abstract, which contains information about itself and the descriptions of its manipulations.
|
||||||
|
|
||||||
|
Three are behavioural:
|
||||||
|
|
||||||
|
Message The process by which an object sends Passing information or invokes a method.
|
||||||
|
Method Accessing, setting or manipulating an object’s information.
|
||||||
|
Polymorphism Different objects can respond to the same message and implement it appropriately.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
Points délicats de la programmation objet
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
L'objectivisme
|
||||||
|
---------------
|
||||||
|
|
||||||
|
L'exemple des critiques de Edsger D. Dijkstra face aux objets (1983)
|
||||||
|
|
||||||
|
Les difficultés de l'objectivisme dans la programmation raisonnée.
|
||||||
|
|
||||||
|
Dans les années 60, les promesses de rédemption des "langages de haut niveau"
|
||||||
|
ne se sont pas matérialisées.
|
||||||
|
|
||||||
|
Les critiques de la lenteur du batch processing et du débugging de la
|
||||||
|
programmation procédurale ont débouché sur la nécessité de "l'interactive
|
||||||
|
programming". Cela devait "faciliter la programmation", "augmenter la
|
||||||
|
lisibilité et la compréhension du code".
|
||||||
|
|
||||||
|
Le fait est que une large part de l'histoire de la programmation peut être
|
||||||
|
écrit en termes de projets à plusieurs millions de dollars qui ont échoué dans
|
||||||
|
leurs objectifs.
|
||||||
|
|
||||||
|
Apparemment la programmation objet ne vient pas "naturellement", car
|
||||||
|
le desing objet demande beaucoup d'entrainement.
|
||||||
|
|
||||||
|
Une approche de la nouveauté consiste à se placer dans une position aussi
|
||||||
|
neutre que possible par rapport à cette nouveauté, par rapport à sa cohérence
|
||||||
|
interne. C'est comme d'apprendre une langue étrangère sans essayer de traduire
|
||||||
|
systématiquement dans sa propre langue. Il faut alors apprendre à "penser"
|
||||||
|
dans cette nouvelle langue.
|
||||||
|
|
||||||
|
La programmation objet est d'une telle nouveauté qu'il faut se libérer des
|
||||||
|
habitudes d'approcher le sujet en termes d'analogies.
|
||||||
|
|
||||||
|
La programmation raisonnée
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
**En programmation objet l'anthropomorphisme est le pire de tout.**
|
||||||
|
|
||||||
|
"And now we have the fad of making all sorts of systems and their components "intelligent"
|
||||||
|
or "smart". It often boils down to designing a wolly non-machine interface that makes
|
||||||
|
the machine as unlike a computer as possible."
|
||||||
|
|
||||||
|
Edsger D. Dijkstra
|
||||||
|
|
||||||
|
Dans le cas de la compréhension d'un programme, nous devrions nous intéresser
|
||||||
|
au programme dans sa logique propre, en ignorant temporairement le fait même
|
||||||
|
que le code va être compilé - transformé en code exécutable.
|
||||||
|
Cette approche est bien connue, elle s'appelle l'approche axiomatique.
|
||||||
|
|
||||||
|
Le point important est ici que le système de représentation anthropomorphique, l'utilisation
|
||||||
|
d'une terminologie antropomorphique érige une barrière à l'application du
|
||||||
|
programme. L'une des conséquences de l'anthropomorphisme en programmation
|
||||||
|
est que les manières les plus opérationnelles de programmer et de raisonner
|
||||||
|
sur les programmes sont alors rejetées comme "contre-intuitives", ou "trop
|
||||||
|
abstraites".
|
||||||
|
|
||||||
|
|
||||||
|
| "I think anthropomorphism is worst of all. I have now seen programs
|
||||||
|
| "trying to do things", "wanting to do things", "believing things to be
|
||||||
|
| true", "knowing things" etc. Don't be so naive as to believe that this use
|
||||||
|
| of language is harmless. It invites the programmer to identify himself
|
||||||
|
| with the execution of the program and almost forces upon him the use of
|
||||||
|
| operational semantics."
|
||||||
|
|
||||||
|
Edsger D. Dijkstra
|
||||||
|
|
||||||
|
|
||||||
|
"The anthropomorphic analogy is misleading. A computer program is a formal
|
||||||
|
system, not a collection of living beings. Forget that at your peril."
|
||||||
|
loup vaillant (loupvaillant.fr)
|
||||||
|
|
||||||
|
Le processus de la programmation raisonnée étant abstrait, sa réalisation est
|
||||||
|
subsumée à son design.
|
||||||
|
Dans ces conditions, un programme est comme un poème : on ne peut pas l'écrire
|
||||||
|
sans d'abord l'écrire. On ne le "conçoit" pas au préalable.
|
||||||
|
|
||||||
|
Mais aujourd'hui on parle de la programmation comme d'un processus de
|
||||||
|
production comme un autre, dont on peut mesurer la productivité.
|
||||||
|
(nombre de lignes de code produites, etc.)
|
||||||
|
|
||||||
|
"The pre-computer object that offers the closest analogy to a well designed
|
||||||
|
piece of software is an equally well-designed mathematical theory."
|
||||||
|
Edsger D. Dijkstra
|
||||||
|
|
||||||
|
Ceci se répercute dans notre manière d'enseigner la programmation.
|
||||||
|
Ce qui est appelé aujourd'hui "méthodologie" joue un rôle de plus en plus
|
||||||
|
important, on privilégie le design au détriment de la conception raisonnée
|
||||||
|
d'un programme.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
Introduction à l'algorithmique
|
Démarches objet
|
||||||
================================
|
================================
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
presentation
|
presentation
|
||||||
fondement
|
BasesObjet
|
||||||
mechanism
|
definition
|
||||||
prompt
|
|
||||||
langage
|
|
||||||
programme
|
|
||||||
modularite
|
|
||||||
modules
|
|
||||||
classes
|
classes
|
||||||
|
fondement
|
||||||
|
langage
|
||||||
|
mechanism
|
||||||
|
programme
|
||||||
|
prompt
|
||||||
|
delicat
|
||||||
|
student
|
||||||
|
modularite
|
||||||
DesignPatterns
|
DesignPatterns
|
||||||
annexes/index
|
annexes/index
|
||||||
|
|
|
@ -4,40 +4,42 @@ Mechanismes objets
|
||||||
L'impossible définition
|
L'impossible définition
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
- ObjectsAreDictionaries - maps that can readily contain "function pointers" or function containers, with language and/or syntax features that assist in or simplify the usage of these function maps.
|
|
||||||
|
|
||||||
Variation: "objects are maps that can map interfaces and/or references to other such maps."
|
|
||||||
|
|
||||||
- OO is the view that EverythingIsa a behavior (including data structures)
|
|
||||||
|
|
||||||
- OO is the "natural extension" of programmer-defined types (sometimes known as user-defined types).
|
|
||||||
|
|
||||||
- Inheritance + Encapsulation (no polymorphism): "Inheritance is what separates abstract data type (ADT) programming from OO programming." Section 19.1 of the Feb 2000 Usenet C++ FAQ, which is also published in expanded form in a popular and influential book. Inheritance without polymorphism, however, is little more than compiler-assisted CopyAndPasteProgramming. Useful, but OO?
|
|
||||||
|
|
||||||
|
|
||||||
Pour être qualifié de Orienté Objet, un langage doit être **pur**.
|
Pour être qualifié de Orienté Objet, un langage doit être **pur**.
|
||||||
|
|
||||||
.. glossary::
|
.. glossary::
|
||||||
|
|
||||||
langage pur
|
langage pur
|
||||||
|
|
||||||
Langae dans lequel tout est objet. Exemples : smalltalk, python
|
Langage dans lequel tout est objet. Exemples : smalltalk, python
|
||||||
|
|
||||||
Les trois grandes qualités
|
|
||||||
|
|
||||||
- We should stop using the term "Object Oriented".
|
- We should stop using the term "Object Oriented".
|
||||||
- plusiers définitions : http://wiki.c2.com/?DefinitionsForOo
|
- plusieurs définitions : http://wiki.c2.com/?DefinitionsForOo
|
||||||
- on ne peut pas en choisir une seule : http://wiki.c2.com/?NobodyAgreesOnWhatOoIs
|
- on ne peut pas en choisir une seule : http://wiki.c2.com/?NobodyAgreesOnWhatOoIs
|
||||||
|
|
||||||
- class based programming
|
Quelques essais de définition technique :
|
||||||
|
|
||||||
In a class-based language (like JavaLanguage or SmalltalkLanguage), every object is an instance of a class. An object contains its own data (instance variables), but its class holds its behaviour (methods). To make a new object, you ask a class to "instantiate" itself.
|
|
||||||
|
|
||||||
|
- Les objets sont des dictionnaires, des clefs-valeurs qui peuvent contenir
|
||||||
|
des pointeurs sur des fonctions. Le reste n'est que sucre syntaxique.
|
||||||
|
|
||||||
|
- Variante: "objects are maps that can map interfaces and/or references to other such maps."
|
||||||
|
|
||||||
|
- OO is the view of **EverythingIsa** a behavior (including data structures)
|
||||||
|
|
||||||
|
- OO is the "natural extension" of programmer-defined types (sometimes known as user-defined types).
|
||||||
|
|
||||||
|
- Inheritance + Encapsulation (no polymorphism): "Inheritance is what separates abstract data type (ADT) programming from OO programming."
|
||||||
|
|
||||||
|
|
||||||
|
class based programming
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
In a class-based language (like Python JavaLanguage or SmalltalkLanguage), every object is an instance of a class.
|
||||||
|
An object contains its own data (instance variables), but its class holds its behaviour (methods). To make a new object, you ask a class to "instantiate" itself.
|
||||||
|
|
||||||
|
|
||||||
An Object Oriented system, language, or environment should include at least Encapsulation, Polymorphism, and Inheritance.
|
An Object Oriented system, language, or environment should include at least Encapsulation, Polymorphism, and Inheritance.
|
||||||
|
|
||||||
|
|
||||||
There is a largely accepted definition of OO: roughly the style encouraged by
|
There is a largely accepted definition of OO: roughly the style encouraged by
|
||||||
Java (classes, encapsulation, inheritance, subtype polymorphism, and even
|
Java (classes, encapsulation, inheritance, subtype polymorphism, and even
|
||||||
sometimes genericity).
|
sometimes genericity).
|
||||||
|
@ -47,36 +49,41 @@ https://en.wikipedia.org/wiki/Class-based_programming
|
||||||
encapsulation
|
encapsulation
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|
||||||
- d'attributs
|
- d'attributs
|
||||||
- de méthode (exposer une interface mais on ne sait pas comment cette interface est codée)
|
- de méthode (exposer une interface mais on ne sait pas comment cette interface est codée)
|
||||||
|
|
||||||
Delegation
|
Delegation
|
||||||
|
|
||||||
Than please define what you think delegation is. Let's start with something concrete:
|
Than please define what you think delegation is. Let's start with something concrete:
|
||||||
If the method call:
|
If the method call::
|
||||||
|
|
||||||
targetObject.method(x1,x2,...,x_n)
|
targetObject.method(x1,x2,...,x_n)
|
||||||
|
|
||||||
Is then resolved in the body of TargetClass.method() to:
|
Is then resolved in the body of TargetClass.method() to:
|
||||||
delegate.method(x1,x2,...,x_n)
|
delegate.method(x1,x2,...,x_n)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Yet another reason is the popularity of languages that brand themselves "OO".
|
Yet another reason is the popularity of languages that brand themselves "OO".
|
||||||
C++, Java, Python, Javascript, Self… New ones pop up daily. That doesn't help
|
C++, Java, Python, Javascript, Self… New ones pop up daily. That doesn't help
|
||||||
define "OO", but it does makes it ever more present.
|
define "OO", but it does makes it ever more present.
|
||||||
|
|
||||||
|
|
||||||
|
les méthodes spéciales
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Les méthodes spéciales permettent de changer la manière dont Python
|
||||||
|
réagit à certains opérateurs et accède aux attributs d’une instance.
|
||||||
|
Les méthodes spéciales sont entourées de deux "__"
|
||||||
|
|
||||||
La liaison retardée
|
La liaison retardée
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|
||||||
Internal polymorphism is the kind of polymorphism that you see in most OO computer languages. When you call a method on an object the actual function called is based on the dynamic type of the object.
|
Internal polymorphism is the kind of polymorphism that you see in most OO computer languages. When you call a method on an object the actual function called is based on the dynamic type of the object.
|
||||||
|
|
||||||
|
|
||||||
Prototypes
|
Prototypes
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|
||||||
A prototype is an object that is used as a template to create other objects. 2 mechanisms are used for this: copy and delegation. When creating a derived object from a prototype, you can copy part of the prototype. The part that isn't copied can still be accessed through a delegation pointer stored in the derived object. When you try to access a member of the derived object, and it isn't there, we walk up the delegation pointer to ask the prototype instead.
|
A prototype is an object that is used as a template to create other objects. 2 mechanisms are used for this: copy and delegation. When creating a derived object from a prototype, you can copy part of the prototype. The part that isn't copied can still be accessed through a delegation pointer stored in the derived object. When you try to access a member of the derived object, and it isn't there, we walk up the delegation pointer to ask the prototype instead.
|
||||||
|
|
||||||
Prototype based programming have lots of interesting implications, that I have no experience with. I don't know how if it helps you write shorter or more modular code, especially compared to other mechanisms. I will just note that prototypes are easily implemented (or emulated) in any dynamic language with first class functions and associative maps.
|
Prototype based programming have lots of interesting implications, that I have no experience with. I don't know how if it helps you write shorter or more modular code, especially compared to other mechanisms. I will just note that prototypes are easily implemented (or emulated) in any dynamic language with first class functions and associative maps.
|
||||||
|
@ -84,7 +91,6 @@ Prototype based programming have lots of interesting implications, that I have n
|
||||||
https://en.wikipedia.org/wiki/Prototype-based_programming
|
https://en.wikipedia.org/wiki/Prototype-based_programming
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
In a prototype-based language, an object can contain both data and behaviour. It's a self-contained thing. To make a new object, you just call the "copy" method on an existing object.
|
In a prototype-based language, an object can contain both data and behaviour. It's a self-contained thing. To make a new object, you just call the "copy" method on an existing object.
|
||||||
http://wiki.c2.com/?PrototypeBasedProgramming
|
http://wiki.c2.com/?PrototypeBasedProgramming
|
||||||
|
|
||||||
|
|
|
@ -1,313 +0,0 @@
|
||||||
La programmation modulaire
|
|
||||||
===========================
|
|
||||||
|
|
||||||
Il s'agit de décomposer un grand programme en
|
|
||||||
morceaux (**modules**) connectés entre eux par des **interfaces** bien
|
|
||||||
définies.
|
|
||||||
|
|
||||||
Ces modules doivent être aussi indépendants que possible.
|
|
||||||
|
|
||||||
module
|
|
||||||
|
|
||||||
ensemble de ressources liées sémantiquement
|
|
||||||
|
|
||||||
interface
|
|
||||||
|
|
||||||
mode d’emploi du module, avec en plus un principe de masquage
|
|
||||||
des informations (partie publique, partie secrète)
|
|
||||||
|
|
||||||
|
|
||||||
Signatures, type abstrait et langage de modules : la programmation modulaire
|
|
||||||
permet d'aller très loin dans la programmation structurée.
|
|
||||||
|
|
||||||
|
|
||||||
Définir des fonctions dans un fichier séparé
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
Les fonctions peuvent être définies dans un fichier et le programme dans un
|
|
||||||
autre fichier séparé. Dans ce cas, pour pouvoir être exécuté directement avec
|
|
||||||
la commande python `nomfichierprogramme.py`, le fichier du programme doit
|
|
||||||
importer d’abord les fonctions du fichier dans lequel les fonctions sont
|
|
||||||
définies.
|
|
||||||
|
|
||||||
1. Fichier de fonctions
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
# Fichier foncmaxliste.py
|
|
||||||
# Recherche le premier élément maximal dans une liste ou
|
|
||||||
#dans une chaine de caractères
|
|
||||||
def max_list(L) :
|
|
||||||
k = len(L)
|
|
||||||
max, x = L[0], 0
|
|
||||||
i = 1
|
|
||||||
while i < k :
|
|
||||||
if max < L[i]:
|
|
||||||
max = L[i]
|
|
||||||
x = i
|
|
||||||
i = i + 1
|
|
||||||
return max, x
|
|
||||||
|
|
||||||
2. Fichier de programme
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Pour utilser les fonctions définies dans d’autres fichiers, le fichier de
|
|
||||||
programme doit commencer par les instructions qui importent ces fichiers de
|
|
||||||
fonctions ou directement les fonctions de ces fichiers. Dans la syntaxe
|
|
||||||
ci-dessous, on importe une ou toutes les fonctions du fichier `foncmaxlist.py`.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
# Fichier progmaxlist.py
|
|
||||||
from foncmaxliste import max_list
|
|
||||||
# ou plus simple:
|
|
||||||
# from foncmaxliste import *
|
|
||||||
print max_list([4,5,6,9,12,5,10,3,18,5,6,7])
|
|
||||||
couple = max_list([4,5,6,9,12,5,10,3,18,5,6,7])
|
|
||||||
print ’Max de L est ’, couple[0]
|
|
||||||
print ’et se trouve à la position ’, couple[1]
|
|
||||||
print max_list(’totovaaumarche’)
|
|
||||||
couple = max_list(’totovaaumarche’)
|
|
||||||
print ’Max de L est ’, couple[0]
|
|
||||||
print ’et se trouve à la position ’, couple[1]
|
|
||||||
|
|
||||||
Au lieu d’importer les fonctions, on peut importer le fichier qui définit les
|
|
||||||
fonctions avec la syntaxe qui suit. Dans ce cas, le fichier de programme sera
|
|
||||||
changé comme suit :
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
# Fichier prog2maxlist
|
|
||||||
import foncmaxliste
|
|
||||||
print foncmaxliste.max_list([4,5,6,9,12,5,10,3,18,5,6,7])
|
|
||||||
# la syntaxe indiquant le chemin d’acces a la fonction max_list utiliser ‘‘.’’
|
|
||||||
couple = foncmaxliste.max_list([4,5,6,9,12,5,10,3,18,5,6,7])
|
|
||||||
print ’Max de L est ’, couple[0]
|
|
||||||
print ’et se trouve à la position ’, couple[1]
|
|
||||||
print foncmaxliste.max_list(’totovaaumarche’)
|
|
||||||
couple = foncmaxliste.max_list(’totovaaumarche’)
|
|
||||||
print ’Max de L est ’, couple[0]
|
|
||||||
print ’et se trouve à la position ’, couple[1]
|
|
||||||
|
|
||||||
L’exécution directe du premier fichier de programme::
|
|
||||||
|
|
||||||
python prog max list.py
|
|
||||||
|
|
||||||
L’exécution directe du seconde fichier de programme::
|
|
||||||
|
|
||||||
python prog2 max list.py
|
|
||||||
|
|
||||||
Définition de l'implémentation d'un module
|
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
Tout fichier qui contient au moins une définition d’une fonction ou d’une
|
|
||||||
variable est appelé un module (une bibliothèque). Le nom du module est le nom
|
|
||||||
du fichier enlevé le suffixe `.py`. Ainsi, un fichier de programme qui contient
|
|
||||||
au moins une définition d’une fonction ou un fichier qui ne contient que des
|
|
||||||
définition de fonctions sont des modules. On peut importer un module ou des
|
|
||||||
fonctions ou variables d’un module dans un programme, comme nous avons vu dans
|
|
||||||
les exemples ci-dessus.
|
|
||||||
|
|
||||||
.. important:: on peut importer un module, ou bien lancer un module en tant que
|
|
||||||
programme executable
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
|
|
||||||
Pour faciliter la programmation, Python définit un certain nombre de **modules internes**,
|
|
||||||
appelés les builtins (la librairie standard).
|
|
||||||
|
|
||||||
Par exemple :
|
|
||||||
|
|
||||||
– Lors de l’ouverture d’une session interactive, on est dans un module interne nommé
|
|
||||||
main . Toutes les variables définies par affectation au niveau de ce module sont valides
|
|
||||||
globalement dans la session.
|
|
||||||
|
|
||||||
– D’autres modules internes sont string, math, random
|
|
||||||
|
|
||||||
Dans une session de travail sous l’interpréteur Python, la première importation d’un mo-
|
|
||||||
dule qui, à part des fonctions qu’elle définit, contient des instruction de programme fait
|
|
||||||
exécuter ces instructions. Dans la même session, les importations suivantes ne font pas
|
|
||||||
exécuter ces instructions. Pour les exécuter, on utilise la fonction reload(nomdumodule)
|
|
||||||
(sans sufffixe .py).
|
|
||||||
|
|
||||||
Exemples d'interface
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
type: son type
|
|
||||||
arguments
|
|
||||||
arg1 : description de l'argument 1
|
|
||||||
arg2 : description de l'argument 2
|
|
||||||
préconditions:
|
|
||||||
arg1 > 10
|
|
||||||
postconditions:
|
|
||||||
result < 19
|
|
||||||
raises: TypeError, AssertionError, SystemError...
|
|
||||||
test: tests nominaux pour chaque cas spécifié
|
|
||||||
|
|
||||||
- L'interface racine carrée
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
racine:
|
|
||||||
type: float -> float
|
|
||||||
arguments x: float, flottant dont on veut calculer la racine
|
|
||||||
pré: x >= 0
|
|
||||||
test: racine 25.0 -> 5.0 ; racine (-25) -> raises TypeError
|
|
||||||
|
|
||||||
- L'interface `lendemain`
|
|
||||||
|
|
||||||
Il faut définir auparavant un type spécifique appelé `date`
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
lendemain: le lendemain est la date qui désigne
|
|
||||||
le jour suivant de la date passée en argument
|
|
||||||
type: date -> date
|
|
||||||
arguments :
|
|
||||||
d: date
|
|
||||||
description: la date dont on veut calculer le lendemain
|
|
||||||
|
|
||||||
Le langages des modules
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
.. code-block:: ocaml
|
|
||||||
|
|
||||||
module type PILE = (* signature (interface) du module *)
|
|
||||||
sig
|
|
||||||
type ’a t
|
|
||||||
val create : unit -> ’a t
|
|
||||||
val push : ’a -> ’a t -> unit
|
|
||||||
val pop : ’a t -> ’a
|
|
||||||
end
|
|
||||||
|
|
||||||
(* implémentation du module *)
|
|
||||||
module Pile : PILE = (* le module est restreint
|
|
||||||
par la signature PILE *)
|
|
||||||
struct
|
|
||||||
type ’a t = ’a list ref
|
|
||||||
let create () = ref []
|
|
||||||
let push x p = p := x::!p
|
|
||||||
let pop p = match !p with [...]
|
|
||||||
let rec print p = match p with [...]
|
|
||||||
end
|
|
||||||
|
|
||||||
- `struct .. end` introduit une collection de définitions, valeurs, types ou modules.
|
|
||||||
C'est une **structure**.
|
|
||||||
|
|
||||||
- `module Nom = struct .. end` permet de donner un nom à cette structure et
|
|
||||||
c'est ça un module. C'est une structure nommée.
|
|
||||||
|
|
||||||
- `sig ... end` introduit une signature de module : une interface pour un module.
|
|
||||||
|
|
||||||
On restreint souvent une structure par une signature pour "cacher" certaines
|
|
||||||
définitions. Une signature de module fournit une **interface** entre l'extérieur
|
|
||||||
et l'intérieur d'un module.
|
|
||||||
|
|
||||||
En dehors du module, on accède à ses composants grâce à la notation pointée
|
|
||||||
|
|
||||||
.. code-block:: ocaml
|
|
||||||
|
|
||||||
let p = Pile.create()
|
|
||||||
Pile.push 45 p
|
|
||||||
|
|
||||||
Les foncteurs
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Si un langage possède un langage de modules, on peut aller plus loin : on peut
|
|
||||||
considérer un module comme étant une expression de base du langage.
|
|
||||||
|
|
||||||
- La signature d'un module peut être considérée comme le type du module
|
|
||||||
- La structure du module peut être considéré comme sa valeur
|
|
||||||
|
|
||||||
Quel est l'intérêt ? On peut alors définir des **foncteurs**.
|
|
||||||
|
|
||||||
foncteur
|
|
||||||
|
|
||||||
"fonction" d'une structure vers une autre structure.
|
|
||||||
On peut ainsi paramétrer un module par un autre module.
|
|
||||||
|
|
||||||
.. code-block:: ocaml
|
|
||||||
|
|
||||||
module Nom (M1 :S1 ) (M2 :S2 ) (M3 :S3 ) ... =
|
|
||||||
struct
|
|
||||||
...
|
|
||||||
end
|
|
||||||
|
|
||||||
On applique un foncteur à des paramètres modules, pour
|
|
||||||
obtenir un nouveau module :
|
|
||||||
|
|
||||||
.. code-block:: ocaml
|
|
||||||
|
|
||||||
module M = F (Titi) (Toto)
|
|
||||||
|
|
||||||
|
|
||||||
Contrainte de type par signature
|
|
||||||
------------------------------------
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
module M =
|
|
||||||
struct
|
|
||||||
type t = int * int * int ;;
|
|
||||||
let make d m y = d, m, y ;;
|
|
||||||
end ;;
|
|
||||||
|
|
||||||
let d = M.make 8 5 8 ;;
|
|
||||||
|
|
||||||
module type S =
|
|
||||||
sig
|
|
||||||
type t ;;
|
|
||||||
val make : int -> int -> int -> t ;;
|
|
||||||
end ;;
|
|
||||||
|
|
||||||
module MS = (M:S) ;;
|
|
||||||
|
|
||||||
MS.make 5 1 2 ;;
|
|
||||||
|
|
||||||
Type et signature
|
|
||||||
------------------
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
# module type A = sig
|
|
||||||
val a: int -> int
|
|
||||||
end ;;
|
|
||||||
module type A = sig val a : int -> int end
|
|
||||||
# module B = struct
|
|
||||||
let a x = x + 1 ;;
|
|
||||||
end;;
|
|
||||||
module B : sig val a : int -> int end
|
|
||||||
# module C = (B:A) ;;
|
|
||||||
module C : A
|
|
||||||
|
|
||||||
# C.a 2 ;;
|
|
||||||
- : int = 3
|
|
||||||
#
|
|
||||||
|
|
||||||
Module auquel on impose une signature
|
|
||||||
-----------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
module type DATE = sig
|
|
||||||
type t
|
|
||||||
val make: int -> t
|
|
||||||
val get_year: t -> int
|
|
||||||
val get_month: t -> int
|
|
||||||
end ;;
|
|
||||||
|
|
||||||
module MR = struct
|
|
||||||
type t = int * int
|
|
||||||
let make x y = (x, y)
|
|
||||||
let get_month (x, y) = x
|
|
||||||
let get_year (x, y) = y
|
|
||||||
end ;;
|
|
||||||
|
|
||||||
module date = (MR:DATE) ;;
|
|
|
@ -1,21 +1,18 @@
|
||||||
Avant propos
|
Avant propos
|
||||||
============
|
============
|
||||||
|
|
||||||
| "**Que nul n'entre ici s'il n'est géomètre**"
|
|
||||||
| Maxime apposée au porche d'entrée de l'École de Platon
|
|
||||||
|
|
||||||
|
| "The anthropomorphic analogy is misleading. A computer program is a formal
|
||||||
- L'honnête programmeur d'aujourd'hui **doit** avoir eu une réflexion approndie sur la nature
|
| system, not a collection of living beings. Forget that at your peril."
|
||||||
des objets. Tous les programmeurs les utilisent, peu savent vraiment de quoi il en retourne,
|
| Loup Vaillant
|
||||||
et très peu nombreux savent définir le paradigme et les mécanismes objets correctement.
|
|
||||||
|
|
||||||
.. FIXME
|
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
||||||
.. glossary:: POO
|
.. glossary::
|
||||||
|
|
||||||
|
POO
|
||||||
|
|
||||||
La programmation orientée objet (POO), ou programmation par objet, est un
|
La programmation orientée objet (POO), ou programmation par objet, est un
|
||||||
paradigme de programmation informatique élaboré par les Norvégiens Ole-Johan
|
paradigme de programmation informatique élaboré par les Norvégiens Ole-Johan
|
||||||
|
@ -40,7 +37,15 @@ Objectifs de ce cours
|
||||||
Il s'agit de :
|
Il s'agit de :
|
||||||
|
|
||||||
- maîtriser et concevoir des objets et des classes,
|
- maîtriser et concevoir des objets et des classes,
|
||||||
|
- utiliser un langage avec une conception objet appropriée
|
||||||
|
- savoir repérer le type de support objet que propose un langage
|
||||||
|
- implémenter des objets et des classes en python
|
||||||
- choisir une représentation appropriée des classes,
|
- choisir une représentation appropriée des classes,
|
||||||
- décomposer en sous-problèmes et affinements successifs à l'aide de la représenation objet,
|
- décomposer en sous-problèmes et affinements successifs à l'aide de la
|
||||||
|
représentation objet ("design objet")
|
||||||
|
- devenir un honnête programmeur d'aujourd'hui, c'est-à-dire avoir une
|
||||||
|
réflexion approfondie sur la nature
|
||||||
|
des objets. Tous les programmeurs les utilisent, peu savent vraiment de quoi il en retourne,
|
||||||
|
et très peu nombreux sont ceux qui savent définir le paradigme et les mécanismes objets correctement.
|
||||||
|
|
||||||
.. FIXME
|
.. FIXME
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
Interactions avec l'utilisateur
|
Prompt objet
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
|
Interactions avec l'utilisateur
|
||||||
|
|
||||||
les prompts
|
les prompts
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
# coding: utf-8
|
||||||
|
# object oriented version
|
||||||
|
|
||||||
|
class Student:
|
||||||
|
def __init__(self, name, birth_date):
|
||||||
|
self.name = name
|
||||||
|
self.birth_date = birth_date
|
||||||
|
self.classroom = None
|
||||||
|
|
||||||
|
def move(self, classroom):
|
||||||
|
self.classroom = classroom
|
||||||
|
|
||||||
|
student1 = Student(name='pierre', birth_date=None)
|
||||||
|
student2 = Student(name='paul', birth_date=None)
|
||||||
|
student3 = Student(name='jacques', birth_date=None)
|
||||||
|
|
||||||
|
|
||||||
|
class Principal:
|
||||||
|
classrooms_registry = dict(pierre='4eme3', paul='4eme2', jacques='4eme5')
|
||||||
|
students = [student1, student2, student3]
|
||||||
|
|
||||||
|
def move_students(self):
|
||||||
|
for student in self.students:
|
||||||
|
classroom = self.classrooms_registry[student.name]
|
||||||
|
student.move(classroom)
|
||||||
|
|
||||||
|
for student in self.students:
|
||||||
|
print "The student: {} is assigned to the class {}".format(student.name, student.classroom)
|
||||||
|
|
||||||
|
|
||||||
|
principal = Principal()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
principal.move_students()
|
|
@ -0,0 +1,23 @@
|
||||||
|
# coding: utf-8
|
||||||
|
# procedural version
|
||||||
|
|
||||||
|
student1 = dict(name='pierre', birth_date=None)
|
||||||
|
student2 = dict(name='paul', birth_date=None)
|
||||||
|
student3 = dict(name='jacques', birth_date=None)
|
||||||
|
|
||||||
|
|
||||||
|
classrooms_registry = dict(pierre='4eme3', paul='4eme2', jacques='4eme5')
|
||||||
|
students = [student1, student2, student3]
|
||||||
|
|
||||||
|
def move_students():
|
||||||
|
for student in students:
|
||||||
|
classroom = classrooms_registry[student['name']]
|
||||||
|
student['classroom'] = classroom
|
||||||
|
|
||||||
|
for student in students:
|
||||||
|
print "The student: {} is assigned to the class {}".format(student['name'], student['classroom'])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
move_students()
|
|
@ -0,0 +1,36 @@
|
||||||
|
Comparaison entre style procédural et style objet
|
||||||
|
==================================================
|
||||||
|
|
||||||
|
Le principal d'un collège est debout en face d'élève de quatrième,
|
||||||
|
qui doivent être ventilés dans leurs classes respectives.
|
||||||
|
Seulement les élèves ne connaissent pas leur classe,
|
||||||
|
seul le principal les connaît.
|
||||||
|
|
||||||
|
Comment le principal peut-il affecter un élève à une classe ?
|
||||||
|
Deux solutions évidentes :
|
||||||
|
|
||||||
|
- emmener chaque étudiant dans sa classe respective
|
||||||
|
- dire à chaque étudiant quelle classe lui est assignée pour qu'il s'y rende pas lui-même
|
||||||
|
|
||||||
|
Dans le monde réel, la seconde solution est évidemment meilleure.
|
||||||
|
Dans le monde de la programmation, les deux se défendent.
|
||||||
|
|
||||||
|
Présentation antropomorphique
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Le cheminement procédural
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
.. literalinclude:: snippets/student_procedural.py
|
||||||
|
:language: python
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
|
||||||
|
Le cheminement objet
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
.. literalinclude:: snippets/student_object.py
|
||||||
|
:language: python
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue