Programmation objet

Motivation

sur ChatGPT, demander "give me a Python program that runs A* on a graph described as a png image (each white pixel is a vertex, and black pixels are obstacles)"

=> le résultat est un code monolithique. => Difficile d'avoir confiance, à comprendre, tester, vérifier => Difficile à améliorer => Difficile de réutiliser le code ailleurs

Struct

  • LISP : en plus des listes, des objets avec des champs/attributs 1960s

Objet

Un objet est un ensemble de données (champs) + fonctions (méthodes). Une classe est une ensemble de champs et de définitions de méthodes.

  • ALGOL W en 1966 : C. A. R. Hoare, champs/attributs et méthodes, mais pas de constructeurs
  • Simula 67 par Ole-Johan Dahl and Kristen Nygaard in Norway :
    • constructeur
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def norm():
        return sqrt(self.x ** 2 + self.y ** 2)

p = Point(2, 3)
print(p.norm())
class Graph:
    def __init__(self, n: int):
        self.nbVertices = n
        self.adjList: list[list[int]] = [[] for _ in range(n)]
    
    def addEdge(self, u:int, v:int):
        self.adjList[u].append(v)
        
    def neighbors(self, v: int) -> list[int]:
        return self.adjList[v]

Encapsulation

L' encapsulation a deux sens : le fait d'avoir les données et les méthodes. Mais aussi de cacher des champs aux utilisateurs.

  • Simula 67 :
    • naissances des champs privés et publics (privés = "hidden")

En Python, mettre __ devant le nom de champs et il est privé.

Apparté Python

[[]] * n VS [[] for _ in range(n)] [2] * 3

Vision d'Alan Kay

Smalltalk 1970

  • Encapsulation
  • Message passing
  • Liaison dynamique ~ Duck typing
class Cat:
    def speak(self):
        print("miaou")

class Dog:
    def speak(self):
        print("waouf")

L: list[Cat | Dog] = [Cat(), Dog(), Cat(), Cat()]

for animal in L:
    animal.speak()
  • isinstance(objet, class)

Héritage

Une classe A hérite de B si tout objet A est un B.

from abc import ABCMeta, abstractmethod

class Animal():
    pass

class Cat(Animal):
    def speak(self):
        print("miaou")

class Dog(Animal):
    def speak(self):
        print("waouf")

L: list[Animal] = [Cat(), Dog(), Cat(), Cat()]

a = Animal() #fails

for animal in L:
    animal.speak()

polymorphisme par héritage

  • issubclass(class1, class2)

Classe abstraite

Une classe abstraite (Abstract Base Classes) est une classe où toutes les méthodes ne sont pas définies.

from abc import ABCMeta, abstractmethod

class Animal(metaclass=ABCMeta):
    def hello(self):
        print("hello")

    @abstractmethod
    def speak(self) -> None:
        raise NotImplementedError

class Cat(Animal):
    def speak(self):
        print("miaou")

class Dog(Animal):
    def speak(self):
        print("waouf")

L: list[Animal] = [Cat(), Dog(), Cat(), Cat()]

a = Animal() #fails

for animal in L:
    animal.hello()
    animal.speak()
  • Simula 67
    • héritage
    • méthodes virtuelles

Tout coder (sans type paramétrées)

Itérateur

  • Objet itérable : liste, etc.

  • Itérateur

  • Générateur

  • CLU (for "CLUsters") par Barbara Liskov en 1973 :

    • types abstraits
    • itérateurs

Types paramétrées (polymorphisme de type)

  • types paramétrées (e.g List[T])
  • types somme (e.g. List[T] | None)
  • pas d'héritage (!)

Finir l'implémentation

Exemple de patron de conception

  • Tableaunoir : patron de conception Command