Il y a pas "plein de contraintes", il y a que les noms de modules et de constructeurs, et seulement eux, doivent commencer par des majuscules. Enfin je sais pas ce que t'appelles "plein" mais bon

.
euh les idées de l'orienté-objet sont déjà dans les modules sinon (enfin l'encapsulation tout ça) (je réponds vite fait hein, pq déjà ça fait super longtemps que j'ai pas touché à ça et ensuite j'ai du taff par-dessus la tête), mais il y a des différences. Même si tout ce qui est faisable avec les objets est probablement aussi faisable sans. Bon entre autres il y a l'héritage et les méthodes virtuelles, les modules n'ont pas d'équivalent il me semble (?)
Mais la différence principale je pense (enfin de mon point de vue) c'est que si tu prends le type Machin.t et le type Truc.t, le seul type générique qui les recouvre tous les deux, c'est 'a, donc tu ne peux pas définir une fonction qui prend comme argument une valeur de l'un ou l'autre de ces deux types mais pas autre chose ; si tu veux le faire tu dois définir un type bidon = Machin of Machin.t | Truc of Truc.t
et genre si tu veux convertir ta valeur en chaîne tu dois te taper un match bidon etc.
alors qu'avec les objets, tu peux écrire une fonction du genre let print_nimportequoi x = print_endline x#to_string
et ta fonction aura un type générique qui lui permet de prendre en argument n'importe quel objet qui possède une méthode to_string.
Tu peux d'ailleurs définir plusieurs classes différentes qui ont *exactement* le même type (c'est-à-dire qui ont des méthodes de noms et de types identiques) mais des contenus complètement différents. Et les objets de ces deux classes sont indiscernables.
Sinon ce qu'on ne peut pas faire avec les classes et qu'on peut faire avec les modules, euh, j'ai pas d'idée là et puis faut que j'aille me coucher

.
Edit : je me pose des questions qui n'ont aucun sens (mais bon faut voir l'heure aussi

)
[digression]
quand tu commences à faire des :
class bidule = let [...] in function x -> let [...] in object [...] end
ça devient chaud de savoir quoi change quand (oui parce que par exemple dans le premier [...] tu peux mettre une ref qui est modifiée dans le second [...] et l'est de nouveau dans le troisième [...]) ET aussi tu peux instancier plusieurs fois la classe, genre :
let cree_bidule = new bidule and cree_bidule_aussi = new bidule in let a = cree_bidule () and b = cree_bidule () and c = cree_bidule_aussi () and d = cree_bidule () and e = cree_bidule_aussi ()
tu peux tester avec un truc comme « class bidule = let compteur = ref 0 in function () -> let numero = incr compteur; !compteur in object method numero = numero end »
si tu veux (bon y a pas besoin de tester pour comprendre ce que ça fait hein, je dis ça comme ça ^^)[/digression]