Главная страница
Навигация по странице:

  • Использование диаграмм классов в качестве визуального средства

  • Инкапсуляция и сокрытие данных

  • ЗАКРЫТЫЕ ДАННЫЕ __________________________________________________________________

  • ПОДПИСИ: ИНТЕРФЕЙСЫ В СОПОСТАВЛЕНИИ С ИНТЕРФЕЙСАМИ ___________________

  • Реальный пример парадигмы «интерфейс/реализация»

  • Рис. 1.12.

  • ПОВЕДЕНИЕ __________________________________________________________________________

  • МНОЖЕСТВЕННОЕ НАСЛЕДОВАНИЕ __________________________________________________

  • Рис. 1.16.

  • Рис. 1.17.

  • Объектно-ориентированный подход. Объектно_ориентированный_подход. Объектно ориентированный подход Мэтт Вайсфельд 5е международное издание ббк 32. 973. 2018


    Скачать 5.43 Mb.
    НазваниеОбъектно ориентированный подход Мэтт Вайсфельд 5е международное издание ббк 32. 973. 2018
    АнкорОбъектно-ориентированный подход
    Дата31.03.2023
    Размер5.43 Mb.
    Формат файлаpdf
    Имя файлаОбъектно_ориентированный_подход.pdf
    ТипДокументы
    #1028905
    страница5 из 25
    1   2   3   4   5   6   7   8   9   ...   25
    Сообщения
    Сообщения — это механизм коммуникаций между объектами. Например, когда объект А вызывает метод объекта В, объект А отправляет сообщение объекту В.
    Ответ объекта В определяется его возвращаемым значением. Только открытые, а не закрытые методы объекта могут вызываться другим объектом. Приведенный далее код демонстрирует эту концепцию:
    public class Payroll{
    String name;
    Person p = new Person();
    p.setName("Joe");
    ...код name = p.getName();
    }
    В этом примере (предполагая, что был создан экземпляр объекта
    Payroll
    ) объект
    Payroll отправляет сообщение объекту
    Person с целью извлечения имени с помощью метода getName()
    . Опять-таки не стоит слишком беспоко- иться о фактическом коде, поскольку в действительности нас интересуют концепции. Мы подробно рассмотрим код по мере нашего продвижения по этой книге.
    Использование диаграмм классов в качестве
    визуального средства
    Со временем разрабатывается все больше средств и методик моделирования, призванных помочь в проектировании программных систем. Я с самого начала использовал UML-диаграммы классов как вспомогательный инструмент в об- разовательном процессе. Несмотря на то что подробное описание UML лежит вне рамок этой книги, мы будем использовать UML-диаграммы классов для иллюстрирования создаваемых классов. Фактически мы уже использовали

    39
    Инкапсуляция.и.сокрытие.данных. .
    диаграммы классов в этой главе. На рис. 1.11 показана диаграмма класса
    Person
    , о котором шла речь ранее в этой главе.
    Рис. 1.11. Диаграмма.класса.Person
    Обратите внимание, что атрибуты и методы разделены (атрибуты располагают- ся вверху, а методы — внизу). По мере того как мы будем сильнее углубляться в объектно-ориентированное проектирование, диаграммы классов будут стано- виться значительно сложнее и сообщать намного больше информации о том, как разные классы взаимодействуют друг с другом.
    Инкапсуляция и сокрытие данных
    Одно из основных преимуществ использования объектов заключается в том, что объекту не нужно показывать все свои атрибуты и поведения. При хорошем объектно-ориентированном проектировании (по крайней мере, при таком, ко- торое повсеместно считается хорошим) объект должен показывать только ин- терфейсы, необходимые другим объектам для взаимодействия с ним. Детали, не относящиеся к использованию объекта, должны быть скрыты от всех других объектов согласно принципу необходимого знания.
    Инкапсуляция определяется тем, что объекты содержат как атрибуты, так и по- ведения. Сокрытие данных является основной частью инкапсуляции.
    Например, объект, который применяется для вычисления квадратов чисел, должен обеспечивать интерфейс для получения результатов. Однако внутренние атри- буты и алгоритмы, используемые для вычисления квадратов чисел, не нужно делать доступными для запрашивающего объекта. Надежные классы проектиру- ются с учетом инкапсуляции. В последующих разделах мы рассмотрим концепции интерфейса и реализации, которые образуют основу инкапсуляции.
    Интерфейсы
    Мы уже видели, что интерфейс определяет основные средства коммуникации между объектами. При проектировании любого класса предусматриваются

    Глава.1..Введение.в.объектно-ориентированные.концепции
    40
    интерфейсы для надлежащего создания экземпляров и эксплуатации объектов.
    Любое поведение, которое обеспечивается объектом, должно вызываться через сообщение, отправляемое с использованием одного из предоставленных интер- фейсов. В случае с интерфейсом должно предусматриваться полное описание того, как пользователи соответствующего класса будут взаимодействовать с этим классом. В большинстве объектно-ориентированных языков программирования методы, являющиеся частью интерфейсов, определяются как public
    ЗАКРЫТЫЕ ДАННЫЕ __________________________________________________________________
    Для.того.чтобы.сокрытие.данных.произошло,.все.атрибуты.должны.быть.объявлены.
    как.
    private
    ..Поэтому.атрибуты.никогда.не.являются.частью.интерфейсов..Частью.
    интерфейсов.классов.могут.быть.только.открытые.методы..Объявление.атрибута.
    как.
    public
    .нарушает.концепцию.сокрытия.данных.
    Взглянем на пример того, о чем совсем недавно шла речь: рассмотрим вычисле- ние квадратов чисел. В таком примере интерфейс включал бы две составляющие:
    ‰
    способ создать экземпляр объекта
    Square
    ;
    ‰
    способ отправить значение объекту и получить в ответ квадрат соответству- ющего числа.
    Как уже отмечалось ранее в этой главе, если пользователю потребуется доступ к атрибуту, то будет сгенерирован метод для возврата значения этого атрибута
    (геттер). Если затем пользователю понадобится получить значение атрибута, то будет вызван метод для возврата его значения. Таким образом, объект, со- держащий атрибут, будет управлять доступом к нему. Это жизненно важно, особенно в плане безопасности, тестирования и сопровождения. Если вы кон- тролируете доступ к атрибуту, то при возникновении проблемы не придется беспокоиться об отслеживании каждого фрагмента кода, который мог бы из- менить значение соответствующего атрибута — оно может быть изменено толь- ко в одном месте (с помощью сеттера).
    В целях безопасности не нужно, чтобы неконтролируемый код мог изменять или обращаться к закрытым данным. Например, во время использования бан- комата нужно ввести пин-код, чтобы получить доступ к данным.
    ПОДПИСИ: ИНТЕРФЕЙСЫ В СОПОСТАВЛЕНИИ С ИНТЕРФЕЙСАМИ ___________________
    Не.стоит.путать.интерфейсы.для.расширения.классов.с.интерфейсами.классов..Мне.
    нравится.обобщать.интерфейсы,.представленные.методами,.словом.«подписи».
    Реализации
    Только открытые атрибуты и методы являются частью интерфейсов. Пользо- ватели не должны видеть какую-либо часть внутренней реализации и могут взаимодействовать с объектами исключительно через интерфейсы классов.

    41
    Инкапсуляция.и.сокрытие.данных. .
    Таким образом, все определенное как private окажется недоступно пользова- телям и будет считаться частью внутренней реализации классов.
    В приводившемся ранее примере с классом
    Employee были скрыты только атри- буты. Во многих ситуациях будут попадаться методы, которые также должны быть скрыты и, таким образом, не являться частью интерфейса. В продолжение примера из предыдущего раздела представим, что речь идет о вычислении ква- дратного корня, и отметим при этом, что пользователям будет все равно, как вычисляется квадратный корень, при условии, что ответ окажется правильным.
    Таким образом, реализация может меняться, однако она не повлияет на поль- зовательский код. Например, компания, которая производит калькуляторы, может заменить алгоритм (возможно, потому, что новый алгоритм оказался более эффективным), не повлияв при этом на результаты.
    Реальный пример парадигмы «интерфейс/реализация»
    На рис. 1.12 проиллюстрирована парадигма «интерфейс/реализация» с исполь- зованием реальных объектов, а не кода. Тостеру для работы требуется электри- чество. Чтобы обеспечить подачу электричества, нужно вставить вилку шнура тостера в электрическую розетку, которая является интерфейсом. Для того чтобы получить требуемое электричество, тостеру нужно лишь «реализовать» шнур, который соответствует техническим характеристикам электрической розетки; это и есть интерфейс между тостером и электроэнергетической компанией (в дей- ствительности — системой электроснабжения). Для тостера не имеет значения, что фактической реализацией является электростанция, работающая на угле. На самом деле электричество, которое для него важно, может вырабатываться как огромной атомной электростанцией, так и небольшим электрогенератором. При такой модели любой прибор сможет получить электричество, если он соответ- ствует спецификации интерфейса, как показано на рис. 1.12.
    Рис. 1.12. Пример.с.электростанцией
    Модель парадигмы «интерфейс/реализация»
    Подробнее разберем класс
    Square
    . Допустим, вы создаете класс для вычисления квадратов целых чисел. Вам потребуется обеспечить отдельный интерфейс

    Глава.1..Введение.в.объектно-ориентированные.концепции
    42
    и реализацию. Иначе говоря, вы должны будете предусмотреть для пользовате- лей способ вызова методов и получения квадратичных значений. Вам также потребуется обеспечить реализацию, которая вычисляет квадраты чисел; одна- ко пользователям не следует что-либо знать о конкретной реализации. На рис. 1.13 показан один из способов сделать это. Обратите внимание, что на диа- грамме класса знак плюс (
    +
    ) обозначает public
    , а знак минус (

    ) указывает на private
    . Таким образом, вы сможете идентифицировать интерфейс по методам, в начале которых стоит плюс.
    Рис. 1.13. Класс.IntSquare
    Эта диаграмма класса соответствует следующему коду:
    public class IntSquare {
    // закрытый атрибут private int squareValue;
    // открытый интерфейс public int getSquare (int value) {
    SquareValue =calculateSquare(value);
    return squareValue;
    }
    // закрытая реализация private int calculateSquare (int value) {
    return value*value;
    }
    }
    Следует отметить, что единственной частью класса, доступной для пользовате- лей, является открытый метод getSquare
    , который относится к интерфейсу.
    Реализация алгоритма вычисления квадратов чисел заключена в закрытом методе calculateSquare
    . Обратите также внимание на то, что атрибут
    SquareValue является закрытым, поскольку пользователям не нужно знать о его наличии.
    Поэтому мы скрыли часть реализации: объект показывает только интерфейсы,

    43
    Наследование. .
    необходимые пользователям для взаимодействия с ним, а детали, не относящи- еся к использованию объекта, скрыты от других объектов.
    Если бы потребовалось сменить реализацию — допустим, вы захотели бы ис- пользовать встроенную квадратичную функцию соответствующего языка про- граммирования, — то вам не пришлось бы менять интерфейс. Вот код, исполь- зующий метод
    Math.pow из Java-библиотеки, который выполняет ту же функцию, однако обратите внимание, что calculateSquare по-прежнему является частью интерфейса:
    // закрытая реализация private int calculateSquare (int value) {
    return = Math.pow(value,2);
    }
    Пользователи получат ту же самую функциональность с применением того же самого интерфейса, однако реализация будет другой. Это очень важно при на- писании кода, который будет иметь дело с данными. Так, например, вы сможе- те перенести данные из файла в базу данных, не заставляя пользователя вносить изменения в какой-либо программный код.
    Наследование
    Наследование позволяет классу перенимать атрибуты и методы другого класса.
    Это дает возможность создавать новые классы абстрагированием из общих атрибутов и поведений других классов.
    Одна из основных задач проектирования при объектно-ориентированном про- граммировании заключается в выделении общности разнообразных классов.
    Допустим, у вас есть класс
    Dog и класс
    Cat
    , каждый из которых будет содержать атрибут eyeColor
    . При процедурной модели код как для
    Dog
    , так и для
    Cat вклю- чал бы этот атрибут. При объектно-ориентированном проектировании атрибут, связанный с цветом, можно перенести в класс с именем
    Mammal наряду со всеми прочими общими атрибутами и методами. В данном случае оба класса —
    Dog и
    Cat
    — будут наследовать от класса
    Mammal
    , как показано на рис. 1.14.
    Итак, оба класса наследуют от
    Mammal
    . Это означает, что в итоге класс
    Dog будет содержать следующие атрибуты:
    eyeColor // унаследован от Mammal barkFrequency // определен только для Dog
    В том же духе объект
    Dog будет содержать следующие методы:
    getEyeColor // унаследован от Mammal bark // определен только для Dog

    Глава.1..Введение.в.объектно-ориентированные.концепции
    44
    Рис. 1.14. Иерархия.классов.млекопитающих
    Создаваемый экземпляр объекта
    Dog или
    Cat будет содержать все, что есть в его собственном классе, а также все имеющееся в родительском классе. Таким об- разом,
    Dog будет включать все свойства своего определения класса, а также свойства, унаследованные от класса
    Mammal
    ПОВЕДЕНИЕ __________________________________________________________________________
    Стоит.отметить,.что.сегодня.поведение,.как.правило,.описывается.в.интерфейсах.
    и.что.наследование.атрибутов.является.наиболее.распространенным.использова- нием.прямого.наследования..Таким.образом,.поведение.абстрагируется.от.своих.
    данных.
    Суперклассы и подклассы
    Суперкласс, или родительский класс (иногда называемый базовым), содержит все атрибуты и поведения, общие для классов, которые наследуют от него. На- пример, в случае с классом
    Mammal все классы млекопитающих содержат анало- гичные атрибуты, такие как eyeColor и hairColor
    , а также поведения вроде generateInternalHeat и growHair
    . Все классы млекопитающих включают эти атрибуты и поведения, поэтому нет необходимости дублировать их, спускаясь по дереву наследования, для каждого типа млекопитающих. Дублирование по- требует много дополнительной работы, и пожалуй, вызывает наибольшее бес- покойство — оно может привести к ошибкам и несоответствиям.
    Подкласс, или дочерний класс (иногда называемый производным), представ- ляет собой расширение суперкласса. Таким образом, классы
    Dog и
    Cat наследу- ют все общие атрибуты и поведения от класса
    Mammal
    . Класс
    Mammal считается суперклассом подклассов, или дочерних классов,
    Dog и
    Cat

    45
    Наследование. .
    Наследование обеспечивает большое количество преимуществ в плане проек- тирования. При проектировании класса
    Cat класс
    Mammal предоставляет значи- тельную часть требуемой функциональности. Наследуя от объекта
    Mammal
    ,
    Cat уже содержит все атрибуты и поведения, которые делают его настоящим классом млекопитающих. Точнее говоря, являясь классом млекопитающих такого типа, как кошки,
    Cat должен включать любые атрибуты и поведения, которые свой- ственны исключительно кошкам.
    Абстрагирование
    Дерево наследования может разрастись довольно сильно. Когда классы
    Mammal и
    Cat будут готовы, добавить другие классы млекопитающих, например собак
    (или львов, тигров и медведей), не составит особого труда. Класс
    Cat также может выступать в роли суперкласса. Например, может потребоваться допол- нительно абстрагировать
    Cat
    , чтобы обеспечить классы для персидских, сиам- ских кошек и т. д. Точно так же, как и
    Cat
    , класс
    Dog может выступать в роли родительского класса для других классов, например
    GermanShepherd и
    Poodle
    (рис. 1.15). Мощь наследования заключается в его методиках абстрагирования и организации.
    Рис. 1.15. UML-диаграмма.классов.млекопитающих
    Такое большое количество уровней наследования является одной из причин, почему многие разработчики стараются в принципе не применять наследование.
    Как часто можно увидеть, непросто определить необходимую степень абстра-

    Глава.1..Введение.в.объектно-ориентированные.концепции
    46
    гирования. Например, представим, что есть классы penguin
    (пингвин) и hawk
    (ястреб). И пингвин, и ястреб — птицы, но должны ли они оба перенимать все признаки класса
    Bird
    (птица), в который заложен метод умения летать?
    В большинстве современных объектно-ориентированных языков программи- рования (например, Java, .NET и Swift) у класса может иметься только один родительский, но много дочерних классов. А в некоторых языках программи- рования, например C++, у одного класса может быть несколько родительских классов. В первом случае наследование называется простым, а во втором —
    множественным.
    МНОЖЕСТВЕННОЕ НАСЛЕДОВАНИЕ __________________________________________________
    Представьте.себе.ребенка,.наследующего.черты.своих.родителей..Какого.цвета.
    у.него.будут.глаза?.То.же.самое.делает.написание.компиляторов.весьма.трудным..
    Вот.C++.позволяет.применять.множественное.наследование,.а.многие.другие.язы- ки.—.нет.
    Обратите внимание, что оба класса,
    GermanShepherd и
    Poodle
    , наследуют от
    Dog
    — каждый содержит только один метод. Однако поскольку они наследуют от
    Dog
    , они также наследуют от
    Mammal
    . Таким образом, классы
    GermanShepherd и
    Poodle включают в себя все атрибуты и методы, содержащиеся в
    Dog и
    Mammal
    , а также свои собственные (рис. 1.16).
    
    
    
    Рис. 1.16. Иерархия.млекопитающих
    Отношения «является экземпляром»
    Рассмотрим пример, в котором
    Circle
    ,
    Square и
    Star наследуют от
    Shape
    . Это отношение часто называется отношением «является экземпляром», поскольку круг — это форма, как и квадрат. Когда подкласс наследует от суперкласса, он

    47
    Полиморфизм. .
    получает все возможности, которыми обладает этот суперкласс. Таким образом,
    Circle
    ,
    Square и
    Star являются расширениями
    Shape
    На рис. 1.17 имя каждого из объектов представляет метод
    Draw для
    Circle
    ,
    Star и
    Square соответственно. При проектировании системы
    Shape очень полезно было бы стандартизировать то, как мы используем разнообразные формы. Так мы могли бы решить, что если нам потребуется нарисовать фигуру любой фор- мы, мы вызовем метод с именем
    Draw
    . Если мы станем придерживаться этого решения всякий раз, когда нам нужно будет нарисовать фигуру, то потребуется вызывать только метод
    Draw
    , независимо от того, какую форму она будет иметь.
    В этом заключается фундаментальная концепция полиморфизма — на индиви- дуальный объект, будь то
    Circle
    ,
    Star или
    Square
    , возлагается обязанность по рисованию фигуры, которая ему соответствует. Это общая концепция во многих современных приложениях, например, предназначенных для рисования и об- работки текста.
    Рис. 1.17. Иерархия.Shape
    Полиморфизм
    Полиморфизм — это греческое слово, буквально означающее множественность форм. Несмотря на то что полиморфизм тесно связан с наследованием, он часто упоминается отдельно от него как одно из наиболее весомых преимуществ объ- ектно-ориентированных технологий. Если потребуется отправить сообщение объекту, он должен располагать методом, определенным для ответа на это со- общение. В иерархии наследования все подклассы наследуют от своих супер- классов. Однако поскольку каждый подкласс представляет собой отдельную сущность, каждому из них может потребоваться дать отдельный ответ на одно и то же сообщение.
    Возьмем, к примеру, класс
    Shape и поведение с именем
    Draw
    . Когда вы попро- сите кого-то нарисовать фигуру, первый вопрос вам будет звучать так: «Какой формы?» Никто не сможет нарисовать требуемую фигуру, не зная формы, ко- торая является абстрактной концепцией (кстати, метод
    Draw()
    в коде
    Shape не содержит реализации). Вы должны указать конкретную форму. Для этого по- требуется обеспечить фактическую реализацию в
    Circle
    . Несмотря на то что

    Глава.1..Введение.в.объектно-ориентированные.концепции
    1   2   3   4   5   6   7   8   9   ...   25


    написать администратору сайта