Программирование на основе классов , или, чаще, ориентация на классы , — это стиль объектно-ориентированного программирования (ООП), в котором наследование происходит посредством определения классов объектов , а не посредством самих объектов (сравните с программированием на основе прототипов ).
Самая популярная и развитая модель ООП — это модель на основе классов, а не модель на основе объектов. В этой модели объекты — это сущности, которые объединяют состояние (т. е. данные), поведение (т. е. процедуры или методы ) и идентичность (уникальное существование среди всех других объектов). Структура и поведение объекта определяются классом , который является определением или планом всех объектов определенного типа. Объект должен быть явно создан на основе класса, и созданный таким образом объект считается экземпляром этого класса. Объект похож на структуру , с добавлением указателей на методы, контроля доступа к членам и неявного члена данных, который находит экземпляры класса (т. е. объекты класса) в иерархии классов (необходимо для функций наследования во время выполнения).
Инкапсуляция не позволяет пользователям нарушать инварианты класса, что полезно, поскольку позволяет изменять реализацию класса объектов для аспектов, не представленных в интерфейсе, без влияния на пользовательский код. Определения инкапсуляции сосредоточены на группировке и упаковке связанной информации ( сплоченности ), а не на вопросах безопасности.
В программировании на основе классов наследование осуществляется путем определения новых классов как расширений существующих классов: существующий класс является родительским классом , а новый класс является дочерним классом . Если дочерний класс имеет только один родительский класс, это называется одиночным наследованием , в то время как если дочерний класс может иметь более одного родительского класса, это называется множественным наследованием . Это организует классы в иерархию , либо дерево (при одиночном наследовании), либо решетку (при множественном наследовании).
Определяющей чертой наследования является то, что наследуются как интерфейс, так и реализация; если наследуется только интерфейс, это известно как наследование интерфейса или подтипирование. Наследование также может осуществляться без классов, как в программировании на основе прототипов .
Языки на основе классов или, если быть точнее, типизированные языки , где подклассы являются единственным способом подтипирования , подвергались критике за смешивание реализаций и интерфейсов — важнейший принцип объектно-ориентированного программирования. Критики говорят, что можно создать класс bag, который хранит коллекцию объектов , а затем расширить его, чтобы создать новый класс, называемый классом set, где дублирование объектов устраняется. [1] [2] Теперь функция, которая принимает объект класса bag, может ожидать, что добавление двух объектов увеличит размер bag на два, однако если передать объект класса set, то добавление двух объектов может увеличить или не увеличить размер bag на два. Проблема возникает именно потому, что подклассы подразумевают подтипирование даже в тех случаях, когда принцип подтипирования, известный как принцип подстановки Лисков , не выполняется. Барбара Лисков и Жанетт Винг кратко сформулировали этот принцип в статье 1994 года следующим образом:
Требование подтипа : Пусть будет свойством, доказуемым для объектов типа . Тогда должно быть истинным для объектов типа , где является подтипом .
Таким образом, обычно необходимо различать подтипирование и подклассирование. Большинство современных объектно-ориентированных языков различают подтипирование и подклассирование, однако некоторые подходы к проектированию этого не делают.
Также еще одним распространенным примером является то, что объект person, созданный из дочернего класса, не может стать объектом родительского класса , поскольку дочерний класс и родительский класс наследуют класс person, но языки на основе классов в основном не позволяют изменять вид класса объекта во время выполнения. Для языков на основе классов это ограничение необходимо для сохранения единого представления класса для его пользователей. Пользователям не нужно беспокоиться о том, что одна из реализаций метода приведет к изменениям, которые нарушат инварианты класса. Такие изменения можно внести, уничтожив объект и построив на его месте другой. Полиморфизм можно использовать для сохранения соответствующих интерфейсов даже при внесении таких изменений, поскольку объекты рассматриваются как абстракции черного ящика и к ним осуществляется доступ через идентификатор объекта . Однако обычно значение ссылок на объекты, ссылающихся на объект, изменяется, что приводит к эффектам в клиентском коде.
Хотя Simula ввела абстракцию классов, каноническим примером языка, основанного на классах, является Smalltalk . Другие включают PHP , C++ , Java , C# и Objective-C .