Après réflexion, je me dis de plus en plus que le LSP s'applique (ou devrait s'appliquer) à tous les polymorphismes. Pas seulement à celui des objets. I.e., il est aussi valide avec le polymorphisme paramétrique.
Dans "On nomme encapsulation cette notion de visibilité des attributs et méthodes d'un objet.", je dirai plutôt: "On nomme encapsulation cette notion de protection des attributs d'un objet pour garantir le respect des invariants de l'objet en offrant une interface dédiée de manipulation de l'objet." (très mal dit). Bref, on ne cache pas pas pour cacher. On cache pour être sûr qu'un tiers couillon, ou nous après une soirée bien arrosée, ne vienne pas altérer, depuis n'importe où et n'importe comment, des données qui participent à une certaine stabilité.
Exemples :
- changer un mot de passe crypté sans passer par la procédure sécurisée qui vérifie l'ancien mot de passe ;
- altérer le dénominateur d'un nombre rationnel alors qu'on l'exploite en supposant qu'il soit toujours strictement positif et la fraction réduite ;
- changer directement (ou mettre directement) un élément à l'intérieur d'une séquence triée
Après techniquement, l'encapsulation s'appuie souvent sur la notion de visibilité pour être mise en oeuvre. À noter que de son coté Eiffel autorise l'accès en lecture aux attributs, mais pas celui en écriture. On a un type d'accessibilité encore différent du public/protégé/privé/package que l'on trouve ailleurs.
Bref, j'ai trouvé la présentation de l'encapsulation trop axée comment (visibilité) et pas assez finalité (à quoi ça sert, pourquoi…). Encapsulation et invariant de classe/instance sont deux notions intimement liées.