Les langages traditionnels orientés-objets comme Java, Smalltalk, Eiffel, C++, etc, diffèrent considérablement de CLOS pour mériter comparaison.
Dans ce type de langages, la classe est aussi l'unité d'encapsulation. Mais chaque méthode est associée à une classe, à la fois syntaxiquement et sémantiquement.
Ceci implique qu'il est impossible de rajouter une méthode à une classe a posteriori sans avoir accès au code source. Rajouter une méthode doit être fait par dérivation de classe, à savoir la création d'une sous-classe dans laquelle la méthode a été rajoutée. Cependant, il est souvent nécessaire de rajouter une méthode à la racine d'une grande arborescence de classes. Il y a plusieurs manières d'y arriver avec un langage orienté-objets traditionnel, chacune ayant ses inconvénients :
En CLOS, cette situation ne pose aucun problème, car il est possible de rajouter une méthode dont les arguments sont spécialisés par des classes existantes, sans avoir accès au code source. Si la spécialisation concerne la racine d'une arborescence, la méthode est valable pour toutes les classes de l'arborescence.
Les langages traditionnels utilisent souvent la sélection simple, à savoir que le choix de la méthode physique à appeler est fait à partir d'un seul argument. Cet argument est tellement spécial que ces langages ont une syntaxe spéciale pour l'indiquer. Au lieu d'écrire f(x,y,z) pour appeler la méthode f avec les arguments x, y et z, le programmeur doit écrire quelque chose comme x.f(y,z), indiquant ainsi que la sélection est faite à partir de l'objet valeur de x.
La sélection simple pose un problème de modélisation orientée-objets. Le plus souvent, une opération d'un protocole doit faire intervenir plusieurs objets de types différents. Exemples :
Un langage traditionnel se doit d'associer la méthode correspondant à ces opérations à la classe d'un seul des objets impliqués, mais cette association complètement artificielle ne concerne que l'implémentation (et non la conception). Il est souvent nécessaire de créer des classes n'ayant aucune raison d'être autre que de simuler la sélection multiple. En CLOS, la sélection multiple est déjà présente.
Avec un langage traditionnel, une classe doit être minimale et complète, à savoir :
En pratique, ceci est très difficile à réaliser, car le concepteur de la classe doit alors penser a priori à toutes utilisations possibles ainsi qu'à tous les besoins au niveau performance de ses applications. Le résultat donne souvent des classes avec beaucoup de méthodes inutiles, mais manquant quand même souvent de méthodes pour une application donnée. CLOS permet l'écriture de classes simples dont la fonctionnalité peut être complétée plus tard en fonction des besoins de l'application.
Certains langages orientés-objets traditionnels ne permettent pas l'héritage multiple, souvent pour des raisons de difficulté d'implémentation. Le langage C++ le permet, et Java de façon restrictive (par le biais des interfaces). L'absence d'héritage multiple peut nuire à la conception. Un objet ne peut pas être de deux types différent simultanément (une fenêtre et un flot, par exemple). Même l'héritage multiple d'interfaces de type Java n'est pas suffisant, car il est souvent impossible de factoriser le code et les déclarations de champs.
Pour les langages orientés-objets traditionnels, la classe est aussi l'unité de protection de données. Des déclarations indiquent la possibilité pour du code externe d'appeler une méthode ou d'accéder à un champ de la classe. En CLOS ces mécanismes sont orthogonaux. Pour la protection, CLOS utilise des paquetages, mais souvent à une granularité moins fine.