Шрифт:
Стоит отметить, что в некотором смысле все методы являются методами класса. Не нужно думать, что, создав сто объектов, мы породили сотню копий кода методов! Однако правила ограничения области видимости гласят, что метод каждого объекта оперирует данными только того объекта, от имени которого вызван. Тем самым у нас создается иллюзия, будто методы объекта ассоциированы с самими объектами.
1.1.2. Наследование
Мы подходим к одной из самых сильных сторон ООП — наследованию. Наследование —- это механизм, позволяющий расширять ранее определенную сущность путем добавления новых возможностей. Короче говоря, наследование - это способ повторного использования кода. (Простой и эффективный механизм повторного использования долго был Святым Граалем в информатике. Много десятилетий назад его поиски привели к изобретению параметризованных процедур и библиотек. ООП - лишь одна из последних попыток реализации искомого.)
Обычно наследование рассматривается на уровне класса. Если нам необходим какой-то класс, а в наличии имеется более общий, то можно определить свой класс так, чтобы он наследовал поведение уже существующего. Предположим, например, что есть класс Polygon, описывающий выпуклые многоугольники. Тогда класс прямоугольника
Если класс
Как мы видели, производный класс может трактовать методы своего базового класса как свои собственные. С другой стороны, он может переопределить метод базового класса, предоставив иную его реализацию. Кроме того, в большинстве языков есть возможность вызвать из переопределенного метода метод базового класса с тем же именем. Иными словами, метод
Отношение между классом и его суперклассом интересно и важно, обычно его называют отношением «является». Действительно, квадрат
Это подводит нас к теме множественного наследования. Можно представить себе класс, который наследует нескольким классам. Например, классы
Множественное наследование, вероятно, наиболее противоречивая часть ООП. Некоторые указывают на потенциальные неоднозначности, требующие разрешения. Например, если в обоих классах
Это скорее проблемы проектировщика языка, а не программиста. В разных объектно-ориентированных языках они решаются по-разному. Иногда вводятся правила, согласно которым какое-то одно определение атрибута «выигрывает». Либо же предоставляется возможность различать одноименные атрибуты. Иногда даже язык позволяет вводить псевдонимы или переименовывать идентификаторы. Многими это рассматривается как аргумент против множественного наследования — о механизмах разрешения подобных конфликтов имен нет единого мнения, поэтому все они «языкозависимы». В языке C++ предлагается минимальный набор средств для разрешения неоднозначностей; механизмы языка Eiffel, наверное, получше, а в Perl проблема решается совсем по-другому.
Есть и альтернатива — полностью запретить множественное наследование. Такой подход принят в языках Java и Ruby. На первый взгляд, это даже не назовешь компромиссным решением, но, вскоре мы убедимся, что все не так плохо, как кажется. Мы познакомимся с приемлемой альтернативой традиционному множественному наследованию, но сначала обсудим полиморфизм — еще одно понятие из арсенала ООП.
1.1.3. Полиморфизм
Термин «полиморфизм», наверное, вызывает самые жаркие семантические споры. Каждый знает, что это такое, но все понимают его по-разному. (Не так давно вопрос «Что такое полиморфизм?» стал популярным во время собеседования при поступлении на работу. Если его зададут вам, рекомендую процитировать какого-нибудь эксперта, например Бертрана Мейера или Бьерна Страуструпа; если собеседник не согласится, то пусть он спорит с классиком, а не с вами.)