Помимо различий в реализации, одно существенное концептуальное различие касается того, когда классы / классы типов объявлены.
Если вы создаете новый класс, MyClass, например, Java или C #, вам нужно указать все интерфейсы, которые он предоставляет во время разработки класса. Теперь, если вы свяжете свой код с библиотекой и предоставите его третьей стороне, они будут ограничены интерфейсами, которые вы выбрали для класса. Если им нужны дополнительные интерфейсы, им нужно создать производный класс, OurDerivedClass. К сожалению, ваша библиотека может делать копии или MyClass, не зная производного класса, и может возвращать новые экземпляры через свои интерфейсы, которые они затем должны будут обернуть. Таким образом, чтобы действительно добавить новые интерфейсы в класс, им нужно было бы добавить новый слой поверх вашей библиотеки. Не элегантный и не очень практичный.
С классами типов вы указываете интерфейсы, которые тип предоставляет отдельно от определения типа. Если сторонняя библиотека теперь содержит YourType, я могу просто создать экземпляр YourType, который будет принадлежать новым интерфейсам (которые вы не предоставили при создании типа) в моем собственном коде.
Таким образом, классы типов позволяют пользователю типа контролировать, с какими интерфейсами придерживается тип, в то время как с «нормальными» классами разработчик класса в контроле (и должен иметь хрустальный шар, необходимый для того, чтобы увидеть все возможные вещи для того, что пользователь может захотеть использовать в классе).