Объект и его свойства. Характеристики ООП
В середине 80-х годов XXв. в программировании возникло новое направление, основанное на понятии объекта. ООП предназначено для написания сложных систем. Возникла потребность разделить программы не просто на процедуры, а на полностью независимые и самостоятельные классы процедур, которые сами отвечают за свое внутреннее состояние и внешнее поведение. Их отличительная черта состоит в том, что базируясь на эти классы, можно строить совершенно различные приложения.
Понятие объекта.Объект– это некая отдельная сущность, выделяющаяся среди других сущностей особыми свойствами, поведением, взаимодействием с себе подобными объектами приложения. Реальные объекты окружающего нас мира обладают тремя базовыми характеристиками: 1.они имеют набор свойств. Совокупность свойств объекта определяет его состояние. Как правило, свойства – это набор переменных и констант, в которых хранятся значения, определяющие параметры объекта. 2.Они способны разными методами изменять эти свойства. Метод–процедура, которая реализует возможные с объектом действия. 3.Способны реагировать на события, возникающие внутри самого объекта. События – это аналог сообщений, которые получают и отправляют объекты. Объекты, имеющие общие свойства, методы обработки данных, объединяются в классы. Класс – это новый тип данных, основанный на единой структуре объекта. При создании класса в современных средах программирования задаются 2 блока: 1.Данные -описываются все структуры данных, с которыми будет работать данный класс, а также создаются экземпляры объектов. 2.Методы-описываются свойства и методы обработки этих данных, еще говорят, описывается поведение данного класса. Классу присваивают имя.
Перед тем как начать создавать класс, необходимо определить три основных момента: 1.Какие действия должны выполнять объекты класса? 2.Что должен содержать класс объектов для выполнения действий? 3.Какие действия присущи объектам данного класса? Класс характеризуется следующими основополагающими понятиями ООП. 1.Наследование.Позволяет создавать новые классы на основе имеющегося класса, с наследованиемвсех его свойств и методов и добавлением собственных. Класс, не имеющий предшественника, называется базовым. Если первый называется базовым, то второй – производным классом (или подклассом). Иерархия. Производный класс сам может служить базовым. От одного базового класса можно образовывать несколько производных. Знание иерархии классов важно для понимания процессов выдачи ответов на сообщение. При получении сообщения объект ищет в протоколе методов экземпляра своего класса метод, совпадающий с именем сообщения. Если такого метода нет, он ищется в списке методов базового класса и т.д. когда метод обнаружен, он выполняется и выдается ответ. Если нигде нет, вплоть до корня дерева, метод не обнаружен, выдается сообщение об ошибке. 2. Полиморфизм.Объекты разных классов могут использовать одноименные методы, работающие по-разному для разных объектов. Или, другими словами, различные объекты выполняют одно и то же действие по-своему. В связи с этим в большинстве случаев методы базового класса у производных классов приходится переопределять. Итак, свойство объектов переопределять методы базового (наследуемого) класса и называется полиморфизмом.Полиморфизм проявляется в том, что одно и то же сообщение может посылаться разным объектам, и понимают они его каждый по-своему. Это увеличивает наглядность программ, поскольку не надо беспокоиться о случайном совпадении имен сообщений. Классы также являются объектами и им тоже можно посылать сообщение. Ведь сообщение – это вызов методов с заданными параметрами. 3.Инкапсуляция.Скрытие сложного механизма действия объекта, т.е. скрытие деталей, несущественных для использования объекта. Определив класс, можно создавать объекты этого класса и манипулировать ими, используя методы. Объекты, принадлежащие одному и тому же типу, образуют коллекцию. Причем, это будут объекты не обязательно одного класса.Свойства.Во многих языках программирования свойства реализуются в виде пары методов: метод, получающий текущее значение свойства, называется акцессор; метод, задающий новое значение свойства — мутатор. Принято называть процедуры свойств именем свойства с приставками get и set.С точки зрения пользователя, свойства выглядят практически так же, как и обычные поля класса. Им можно присваивать некоторые значения и получать их обратно. Свойства позволяют не только возвращать и изменять значение внутренней переменной класса, но и выполнять дополнительные функции.
События.Событийная модель применяется повсеместно, но наиболее часто при создании интерфейса пользователя, когда каждое действие пользователя представляется в виде события и передается определенному объекту. Для объявления события в C# используются делегаты. Когда происходит событие, вызываются все методы делегатов, переданных классу клиентами. События могут использоваться только в том классе, в котором они описаны и не могут напрямую использоваться в порожденных классах.
12.Классы в C#. Форма определения класса. Члены класса: методы, поля, свойства и события.
Одним из основных понятий является класс. Класс – структура данных, содержащая члены-данные (такие как константы и поля), функциональные члены (методы, свойства, события, индексаторы, операторы, конструкторы и деструкторы) и вложенные типы. Классы поддерживают наследование. Простейшее объявление класса выглядит так:// Класс объявленный как public, доступен отовсюду, включая другие сборки// Можно также написать internal - класс будет доступен только из текущей сборкиpublicclassHelloWorldClass {publicvoidHelloWorld() {Console.WriteLine("Hello, world");}} Члены классовКласс определяется как список своих членов. К членам класса относятся его поля (свойства) и функции (методы). Каждому члену класса можно установить его область доступа (accesscontrollevel). Область доступа члена класса определяет участки кода, из которых к этому члену будет возможно обращаться. Каждый член класса имеет признаки: public, protected, internal, protected internal, or private. internal: доступен только при ассемблировании; internalprotectedдля обеспечения дополнительной гибкости; к члену класса могут иметь доступ либо классы из той же сборки, либо подклассы данного класса. private(закрытый, внутренний член класса доступен только из класса) — обращения к члену допускаются только из кода методов класса, в котором этот член определён. Любые наследники класса уже не смогут получить доступ к этому члену;protected(защищённый, внутренний член иерархии классов, доступен только от полученных классов) — обращения к члену допускаются из кода методов класса, в котором этот член определён, или из любых его классов-наследников; public(открытый член класса, доступен для всего кода) — обращения к члену допускаются из любого кода. Методы.Методы могут объявляться для принятия некоторого числа аргументов. Ключевое слово ref может использоваться для передачи значения по определенной ссылке, которая позволяет возвращать значение. Ключевое слово out также вызывает переход по ссылке без передачи значения.
Виртуальные методы. Прежде, чем метод в базовом классе будет переписан, он должен быть объявлен как virtual. Метод в подклассе, который будет переписан, должен быть объявлен с помощью ключевого слова override. Это предотвратит случайную перезапись метода. Методы представляют собой действия, которые можно произвести в связи с данным классом. Возможныемодификаторы - ужеописанные public, static, protected, abstract иеще virtual, override, new и extern. Методам также можно передавать параметры, которые параметризуют его действия.
Метод ReadLine.Метод ReadLine читает из потока ввода строку текста (она завершается символом перевода строки или возврата каретки).
Методы Write и WriteLine.Метод Write выводит на экран значение переданной ему переменной. Он определен для всех базовых типов и поддерживает форматированные строки. Т.обр, можно либо вызвать Write с указанным значением в качестве параметра, либо передать строку форматирования и список значений.
Метод Main - это точка входа в программу. С него начинается выполнение. Этот метод обязательно должен быть статическим. Далее в нашем примере используется метод WriteLine из класса System.Console. Этот метод отправляет строку на стандартный вывод. Поле класса.Поле класса (переменная-член, datamember, classfield, instancevariable) в объектно-ориентированном программировании — переменная, связанная с классом или объектом. Все данные объекта хранятся в его полях. Доступ к полям осуществляется по их имени. Обычно тип данных каждого поля задаётся в описании класса, членом которого является поле.
Поля структур.Структурные типы, поддерживаемые большинством языков программирования (называемые структурами (structure) в Си, записями (record) в Паскале и т.д.), являются частным случаем классов — а именно, классами из одних только полей. Вся информация, относящаяся к полям классов, в равной степени относится и к структурным типам. Статические поля.Обычно каждому объекту соответствуют собственные значения всех его полей. Также к полям класса относят статические поля (staticdatamembers, staticclassfields, classvariables) — поля, общие для всех объектов класса.Статические поля семантически не отличаются от обычных глобальных переменных, но они доступны только по указанному имени класса, и поэтому, в отличие от глобальных переменных, не загромождают пространство глобальных имён. Битовые поля.Эти поля занимают менее одной единицы памяти (байт, слово); компилятор сам упаковывает несколько битовых полей в одну единицу памяти, позволяя при этом обращаться к битовым болям как к отдельным полям класса. Понятие битовых полей не ограничивается полями классов: по аналогии оно было перенесено и на другие случаи упаковки в одну единицу памяти нескольких значений, например в сетевых протоколах и в форматах файлов. Поля только для чтения (readonly Fields).Поскольку переменные многих типов не могут быть константами, в некоторых ситуациях использовать ключевое слово const невозможно.
В Си Шарп события неотъемлемо связаны с делегатами. Именно на делегатах основана вся модель событий в C#. Чаще всего события (events) используются в windows приложениях в которых допустим кнопка Button реагируя на события, выдают информацию на той же панели где они расположены (например щелчок мышкой). Но события так же можно использовать и в консольных приложениях.
События имеют следующие свойства: 1) Издатель определяет момент вызова события, подписчики определяют предпринятое ответное действие. 2) У события может быть несколько подписчиков. Подписчик может обрабатывать несколько событий от нескольких издателей. 3) События, не имеющие подписчиков, никогда не возникают. 4) Обычно события используются для оповещения о действиях пользователя, таких как нажатия кнопок или выбор меню и их пунктов в графическом пользовательском интерфейсе. 5) Если событие имеет несколько подписчиков, то при его возникновении происходит синхронный вызов обработчиков событий. 6) События можно использовать для синхронизации потоков. 7) В библиотеке классов .NET Framework в основе событий лежит делегат EventHandler и базовый класс EventArgs.
13.Конструкторы. Параметризованные конструкторы. Использование оператора new.
Конструктор – это специальный метод, который инициализирует объект при его создании. Характеристика конструкторов.
Формат записи: 1) имя конструктора совпадает с именем класса; 2) конструктор не может возвращать значения; 3) конструкторы могут быть перегружены.
Обычно в качестве модификационного доступа используется public, т.к. конструктор вызывается вне класса (чаще всего). Если вы не создали конструктор, то компилятор C# автоматически предоставляет конструктор по умолчанию, который инициализирует все переменные члены, имеющие тип значений нулями, а переменные- члены ссылочного типа – null- значениями. Примечание: конструктор класса по умолчанию- это конструктор, который не принимает никаких параметров. Чаще используют конструкторы, которые принимают один или несколько параметров, чтобы инициализировать ответ в момент его создания, установив ему нужные значения. Процесс создания и использования нескольких конструкторов с одинаковым именем называют перегрузкой конструктора. Примечание: Перегрузка- один из видов полиморфизма. Благодаря перегрузке конструкторов могут меняться различные способы создания объектов. Вызов того или иного конструктора определяется набором передаваемых ему параметров (сигнатурой).
При использовании newCLR выделяет память и вызывает конструктор. Конструктор – это специальные метод, который называется также как и класс, может иметь параметры, но не может возвращать значение (даже void). Каждый класс должен иметь конструктор, если его не создали, то конструктор создастся по умолчанию.
При создании объекта структуры с помощью оператора new объект создается и вызывается соответствующий конструктор.В отличие то классов структуры можно создавать без использования оператора new.В таком случае вызов конструктора отсутствует, что делает выделение более эффективным.Однако поля остается без значений и объект нельзя использовать до инициализации всех полей.
Когда структура содержит ссылочный тип в качестве члена, конструктор по умолчанию члена должен вызываться явно, в противном случае член останется без значений и структура не сможет использоваться.
14. Типы значений и ссылочные типы. Динамическое использование памяти: стеки и кучи. Упаковка и распаковка.
Все типы в C# разделяются на две основные разновидности: структурные типы (value- based) или типы значений и ссылочные типы (reference- based). К структурным типам относятся все числовые типы данных (int, float и пр.), а также перечисления и структуры. При присвоении одного структурного типа другому присваивается не сам тип (как область в памяти), а его побитовая копия. Память для структурных типов выделяется из стека.Стек резервируется для хранения данных, создаваемых во время компиляции программы. В стеке применяется принцип обслуживания типа LiFO (LastinFirstOut – последним применен- первым обслужен). Согласно этому методу, первым обрабатывается последний из поступивших запросов. Выделение памяти. Выделение памяти из кучи в среде NetRuntime происходит очень быстро. Система убеждается в том, что в управляемой куче хватает памяти для запрашиваемого объекта, возвращает указатель на эту память и переводит указатель на следующий после последнего объекта адрес. Когда операционная система запускает приложение на выполнение, CLR резервирует непрерывный диапазон адресов адресного пространства, который называют управляемой кучей. Указатель NextPtr (NextPointer) сохраняет адрес кучи, в который может быть размещён следующий объект. В начальный момент, когда в куче ещё нет ни одного объекта, этот указатель указывает на базовый адрес зарезервированного адресного пространства. После того как приложение использует оператор new для создания объекта, CLR проверяет доступно ли в куче необходимое количество байт. После чего указатель NextPtr вызывает адрес для нового объекта в куче. Вызывается конструктор объекта. Оператор new возвращает адрес. После этого значение указателя NextPtr увеличивается и он сохраняет адрес для записи следующего объекта в управляемой куче. Указатель NextPtr ← Объект А; Объект В; Объект С. Типы значений можно разделить на 3 группы: простые типы, структуры и перечисление. Ссылочные типы (классы, интерфейсы, массивы, строки) хранят ссылки на данные, вместо действительных данных и ведут себя по- другому. Память для них выделяется не в стеке, а в области управляемой кучи. Ссылочная переменная содержит информацию о месте хранения, т.е. ссылку на данные. Каждая активная ссылка на объект в памяти называется корнем.
Ссылки указывают на местонахождение объектов в управляемой куче. Когда много создано объектов, пространство в управляемой куче может закончится. Тогда автоматически запускается сборщик мусора. Он отслеживает, есть ли в куче активные ссылки. Если ссылок на объект нет или объект установлен на null, то объект помечается для удаления. При копировании ссылочного типа создаётся ещё одна ссылка, которая указывает на туже область оперативной памяти. Можно изменить исходный объект. studentstud3= stud1; Обе переменные stud1 и stud3 ссылаются на один и тот же объект. На этот объект можно воздействовать, используя либо stud1, либо stud3. stud3.Addstip (-10000); stud3. Show_Student ( ); stud1. Show_Student ( ); (Получаемодинитожезнак). От структурного типа к ссылочному типу и наоборот: упаковка и распаковка. В C# предусмотрен очень простой механизм для преобразования структурного типа в ссылочный. Он получил название упаковки (boxing). Предположим, что у нас есть (создаём переменную S) shortS=25;
А вот как выглядит процесс упаковки – преобразование объекта структурного типа в ссылочный: (Упаковываем переменную S) objectobjshort=s; (наше имя)
Упаковка- это процесс явного преобразования структурного типа в ссылочный. При этом происходит следующее: в управляемой куче создаётся новый объект и в него копируются внутренние данные старого объекта из стека (у нас-25). Противоположная операция называется распаковкой (unboxing). Распаковка– это преобразование ссылки на объект в оперативной памяти обратно в структурный тип. Перед выполнением распаковки среда выполнения CLR производит проверку на совместимость между типом объекта в оперативной памяти и тем структурным типом, в который будет производиться распаковка. (Обратная распаковка объекта)
shortanotherShort=(short) obj’short; Если же среда выполнения обнаружит, что происходит распаковка в неподходящий тип данных, будет сгенерировано исключение InvalidCastException. (Неверная распаковка) StringStr=(string)obj’short;
В большинстве случаев операции по упаковке и распаковке выполняются компилятором в C# полностью автоматически. Например, если структурный тип передаётся методу, который принимает в качестве параметра объект, упаковка произойдёт автоматически. Явная упаковка и распаковка используется в C# только тогда, когда это повысит производительность приложения.
15. Деструкторы. Сборка «мусора».
Деструкторы – это специальный метод, который вызывается перед тем, как объект будет окончательно разрушен системой сбора мусора. Он обеспечивает гарантию «чистой» ликвидации объекта. Деструктор используется для операций освобождения памяти, выделенной для объектов класса. Формат записи: имя_класса ( ) код деструктора. Характеристики деструктора:1) имя деструктора совпадает с именем класса; 2) для деструктора неявно устанавливается спецификатор доступа public; 3) деструктору нельзя передать аргументы, поэтому в классе может быть определён только один деструктор. Деструктор не возвращает значения. Он вызывается в момент предшествующий процессу утилизации объекта. В теле действительно указываются действия, которые должны быть выполнены перед разрушением объекта. Сборка мусора.После генерации машинного кода он выполняется на определённой платформе. На этом этапе осуществляется очень важные действия- сборка мусора. Управление ресурсами в программе может оказаться довольно сложной задачей. Как правило, в приложении задействовано значительное количество ресурсов, например, записи без данных, сетевые соединения, пространство экрана монитора и т.д. В ситуации, когда после использования памяти, выделенной для ресурса, она не освобождается, или доступ к ресурсу продолжается несмотря на освобождение памяти, работа приложения становится нестабильной и непредсказуемой. Для предотвращения подобных проблем разработана программа сборщика мусора. Сборщик мусора – один из наиболее важных компонентов среды CLR. Он освобождает программиста от утомительной задачи контроля использования и своевременного освобождения памяти. Например, если программист установил сетевое соединение и больше не нуждается в нём, то сборщику мусора не будет известно о необходимости разрыва сетевого соединения до освобождения области памяти, выделенной для этого соединения. Поэтому программист должен в программном коде написать, как правильно следует освобождать ресурс. В среде .NET программисты создают такой код с помощью деструктора или методов CLOSE или DISPOSE. Сборщик мусора освобождает память, занимаемую неиспользуемыми объектами. Иными словами, при удалении последней ссылки на объект он становится кандидатом на удаление сборщиком мусора. Процесс вызова деструктора или прекращение дальнейшего использования объекта называют завершением (finalization). Основная проблема сборки мусора заключена в том, что невозможно точно предсказать, когда сборщик мусора освободит память. Обычно это происходит при недостатке объёма памяти для хранения данных создаваемых объектов. В результате могут возникнуть ситуации, когда деструктор объекта вообще не буде вызван. Даже на этапе завершения работы приложения CLR может пропустить процесс вызова деструктора объекта с целью ускорить завершение работы. Поэтому рекомендуется не выполнять важные операции освобождения памяти с помощью деструктора. Желательно создать отдельный метод, в который можно добавить операции по завершению работы (например, закрытие файла или обновление записей в базе данных). Затем необходимо определить явный вызов этого метода.