- •2.Основные понятия объектно-ориентированного программирования — класс, объект, поле, метод, свойство.
- •4.Конструкторы и деструкторы. Функциональное назначение. Виды конструкторов.
- •5.Объекты и их жизненный цикл. Создание и уничтожение объектов.
- •6. Инкапсуляция. Определение. Функциональное назначение. Реализация. Примеры применения
- •7 Инкапсуляция. Свойства. Функциональное назначение. Реализация. Создание индексатора. Примеры применения.
- •8.Инкапсуляция. Скрытие членов класса. Функциональное назначение. Реализация. Примеры применения.
- •9.Наследование. Функциональное назначение. Реализация. Примеры применения.
- •10.Наследование. Конструктор по умолчанию. Назначение.
- •13. Методы. Определение. Функциональное назначение. Способы реализации. Примеры применения.
- •14.Полиморфизм. Функциональное назначение. Способы реализации. Примеры применения.
- •15.Перегрузка методов. Функциональное назначение. Способ реализации. Примеры применения.
- •16.Виртуальные методы. Функциональное назначение. Примеры применения.
- •17.Перегрузка операций. Функциональное назначение. Способ реализации. Примеры применения.
- •19.Исключительные ситуации. Понятие. Способы обработки исключительных ситуаций. Примеры применения.
- •20.Интерфейсы. Функциональное назначение. Иерархия интерфейсов. Множественное наследование: проблемы и способы их разрешения.
- •Interface имя{ тип_возврата имя_метода1 {список_параметров) ;
- •Void iProps.Prop3() { Console.WriteLine("Свойство 3 интерфейса 1"); }
- •Void iPropsOne.Prop3() { Console.WriteLine("Свойство 3 интерфейса 2"); }
- •21. Структуры (struct) и перечисления (enum). Отличия структур от классов.
- •1 RedDel имеет значение 2
- •Концепция типа данных. Встроенные типы данных и их реализация в языке с#
- •Концепция типа данных. Соглашения о совместимости и приведение типов
- •Концепция типа данных. Числовые типы данных.
- •Концепция типа данных. Символьные типы данных.
- •Концепция типа данных. Составные типы данных. Массивы и их реализация в с#. Структуры.
- •Концепция типа данных. Явное и неявное преобразование типов.
- •7. Концепция типа данных. Определение собственных типов данных.
- •Концепция типа данных. Значащие (размерные) (Value type) и ссылочные (Reference type) типы данных. Упаковка и распаковка (Boxing, Unboxing).
- •Концепция типа данных. Переменные и константы и их реализация в с#.
- •10. Принцип модульности программ. Глобальные и локальные имена. Область видимости имен. Выбор области видимости.
- •11. Принцип модульности программ. Метод, как отдельный модуль программы. Интерфейсная и скрытая часть метода. Формальные и фактические параметры метода. Примеры применения.
- •12. Унарные и мультипликативные операции. Примеры применений.
- •13. Аддитивные и сдвиговые операции. Примеры применений.
- •14. Операции отношения и действий над типами данных. Примеры применений.
- •If (a is a) Console.WriteLine("Объект а имеет тип a.");
- •If(b is в) Console.WriteLine("Объект b имеет тип в."); if(a is object) Console.WriteLine("а — это объект."); }}
- •15. Логические операции. Примеры применений.
- •16. Организация циклов в с#. Примеры применений.
- •17. Операторы перехода и оператор присваивания.
- •18. Операторы условного перехода. Примеры применений.
16.Виртуальные методы. Функциональное назначение. Примеры применения.
Виртуальным называется метод, объявляемый с помощью ключевого слова virtual в базовом классе и переопределяемый в одном или нескольких производных классах. Таким образом, каждый производный класс может иметь собственную версию виртуального метода. Какую именно версию метода нужно вызвать, С# определяет по типу объекта, на который указывает эта ссылка, причем решение принимается динамически, во время выполнения программы. Следовательно, если имеются ссылки на различные объекты, будут выполняться различные версии виртуального метода. Другими словами, именно тип объекта, на который указывает ссылка (а не тип ссылки) определяет, какая версия виртуального метода будет выполнена. Чтобы объявить метод в базовом классе виртуальным, его объявление необходимо предварить ключевым словом virtual. При переопределении виртуального метода в производном классе используется модификатор override. Итак, процесс переопределения виртуального метода в производном классе иногда называется замещением метода (method overriding). При переопределении метода сигнатуры типа у виртуального и метода-заменителя должны совпадать. Кроме того, виртуальный метод нельзя определять как статический (с использованием слова static) или абстрактный (с использованием слова abstract).
Если производный класс не переопределяет виртуальный метод в случае многоуровневой иерархии, то будет выполнен первый переопределенный метод, который обнаружится при просмотре иерархической лестницы в направлении снизу вверх.
Переопределение методов позволяет С# поддерживать динамический полиморфизм. Без полиморфизма объектно-ориентированное программирование невозможно, поскольку он позволяет исходному классу определять общие методы, которыми будут пользоваться все производные классы, и в которых при этом можно будет задать собственную реализацию некоторых или всех этих методов. Переопределенные методы представляют собой еще один способ реализации в С# аспекта полиморфизма, который можно выразить как "один интерфейс — много методов".
Пример:
Class TwoDShape {
Public virtual double area() { Console.WriteLine("Метод area() необходимо переопределить. " ) ;
return 0.0; }}
class Triangle : TwoDShape { // Класс треугольников, производный от класса TwoDShape
public override double area() { // Переопределяем метод аrеa() для класса Triangle
return width * height / 2 ; } }
class Rectangle : TwoDShape { // Класс прямоугольников, производный от класса TwoDShape
public override doubl earea() {// Переопределяем метод аrеа() для класса Rectangle,
return width * height; } }
public static void Main() {
TwoDShape shape1 = new TwoDShape();
TwoDShape shape2 = new TwoDShape();
shape1= new Triangle();
shape2= new Rectangle(); }
Каждое переопределение метода area () реализует вариант вычисления площади, соответствующий типу объекта, инкапсулируемому производным классом.
17.Перегрузка операций. Функциональное назначение. Способ реализации. Примеры применения.
Под перегрузкой операции понимается существование нескольких реализаций одной и той же операции. Большинство операций языка C# перегружены - одна и та же операция может применяться к операндам различных типов. Поэтому перед выполнением операции идет поиск реализации, подходящей для данных типов операндов. Операции, как правило, выполняются над операндами одного типа. Если же операнды разных типов, то предварительно происходит неявное преобразование типа операнда.
Язык С# позволяет определить значение оператора относительно создаваемого класса. Этот процесс называется перегрузкой операторов. Перегружая оператор, вы расширяете его использование для класса. Результат действия оператора полностью находится в ваших руках, и может быть разным при переходе от класса к классу.
При перегрузке оператора ни одно из его исходных значений не теряется. Перегрузку оператора можно расценивать как введение новой операции для класса. Эта расширяемость типов — важная составляющая мощи таких объектно-ориентированных языков программирования, как С#. Если для класса определены некоторые операторы, вы можете оперировать объектами этого класса, используя обычный С#-синтаксис выражений. Более того, вы можете использовать в выражениях объект, включающий другие типы данных. Перегрузка операторов — одно из самых мощных средств языка С#. Перегрузка операторов тесно связана с перегрузкой методов. Для перегрузки операторов используется ключевое слово operator, позволяющее создать операторный метод, который определяет действие оператора, связанное с его классом. Существует две формы методов operator: одна используется для унарных операторов, а другая — для бинарных. Общий же формат (для обоих случаев) таков:
public static тип_возврата operator ор{ тип_параметра операнд)
{// операции}
// Общий формат перегрузки для бинарного оператора,
public static тип_возврата operator op{тип_параметра1 операнд1, тип_параметра2 операнд2) {// операции }
Здесь элемент ор — это оператор (например " + " или " / " ), который перегружается. Пример:
public static Rational operator +(Rational r1, Rational r2)
{ return (r1.Plus(r2)); }//метод Plus складывает дроби
18. Управление областями видимости членов класса. Функциональное назначение. Способ реализации. Примеры применения.
До сих пор все переменные, с которыми мы имели дело, объявлялись в начале метода Main(). Однако в С# разрешается объявлять переменные внутри любого блока. Блок начинается открывающей, а завершается закрывающей фигурными скобками. Любой блок определяет область объявления, или область видимости (scope) объектов. Таким образом, при создании блока создается и новая область видимости, которая определяет, какие объекты видимы для других частей программы. Область видимости также определяет время существования этих объектов.
Самыми важными в С# являются области видимости, которые определены классом и методом. Область видимости класса (и переменные, объявленные внутри нее) мы рассмотрим позже, когда доберемся до описания классов, а пока затронем области видимости, определяемые методами. Область видимости, определяемая методом, начинается с открывающей фигурной скобки. Но если метод имеет параметры, они также относятся к области видимости метода.
Как правило, переменные, объявленные в некоторой области видимости, невидимы (т.е. недоступны) для кода, который определяется вне этой области видимости. Таким образом, при объявлении переменной внутри области видимости вы локализируете ее и защищаете от неправомочного доступа и/или модификации. Эти правила области видимости обеспечивают основу для инкапсуляции. Области видимости могут быть вложенными. Например, при каждом создании программного блока создается новая вложенная область видимости. В этом случае внешняя область включает внутреннюю. Это означает, что объекты, объявленные внутри внешней области, будут видимы для кода внутренней области. Но обратное утверждение неверно: объекты, объявленные во внутренней области, невидимы вне ее. Чтобы лучше понять суть вложенных областей видимости, рассмотрим следующую
программу:
// Демонстрация области видимости блока.
using System;
class ScopeDemo {
public static void Main() {
int x; // Переменная х известна всему коду в пределах
// метода Main().
х = 10;
if(х — 10) { // Начало новой области видимости,
int у = 20; // Переменная у известна только этому блоку.
// Здесь известны обе переменные х и у.
Console.WriteLine("х и у: " + х + " " + у );
х = у * 2;
}
// у = 100; // Ошибка! Переменная у здесь неизвестна.
// Переменная х здесь известна.
Console.WriteLine("Значение х равно " + х );
Как утверждается в комментариях, переменная х объявляется в начале области видимости метода Main () и потому доступна всему последующему коду метода. Внутри блока инструкции i f объявляется переменная у. А поскольку блок определяет область видимости, то переменная у видима только коду внутри этого блока. Поэтому, находясь вне этого блока, программная строка
I // у = 100; // Ошибка! Переменная у здесь неизвестна. оформлена как комментарий. Если убрать символ комментария, компилятор выдаст сообщение об ошибке, поскольку переменная у невидима вне if-блока. Переменную х можно свободно использовать и внутри if-блока, поскольку внутренний код этого блока (т.е. код во вложенной области видимости) имеет доступ к переменным, объявленным вне его.
Внутри блока переменные можно объявлять в любой точке, но действительными
они становятся только после объявления. Таким образом, если объявить переменную
в начале метода, она будет доступна всему коду этого метода. И наоборот, если объя-
вить переменную в конце метода, она будет попросту бесполезной ввиду отсутствия
кода, который мог бы ее использовать.
Переменные создаются после входа в их область видимости, а разрушаются при
выходе из нее. Это означает^ что переменная не будет хранить значение за пределами
области видимости. Таким образом, переменная, объявленная внутри некоторого ме-
тода, не будет хранить значение между вызовами этого метода. И точно так же пере-
менная, объявленная внутри некоторого блока, потеряет свое значение по завершении
этого блока. Следовательно, время существования переменной ограничивается ее об-
ластью видимости.
Если объявление переменной включает инициализатор, такая переменная будет
повторно инициализироваться при каждом входе в блок, в котором она объявляется,
рассмотрим, например, следующую программу:
// Демонстрация времени существования переменной.
using System;
class VarlnitDemo {
public static void Main() { /
int x;
for(x = 0; x < 3; x++) {
int у = -1; // Переменная у инициализируется при
// каждом входе в программный блок.
Console.WriteLine("Значение у равно: " + у); // Здесь всегда выводится -1.
у = 100;
Console.WriteLine("Теперь значение у равно: " + у);
Вот какие результаты генерирует эта программа:
Значение у равно; -1
Теперь значение у равно: 100
Значение у равно: -1
Теперь значение у равно: 100
Значение у равно: -1
Теперь значение у равно: 100
Как видите, при каждом входе в цикл for переменная у неизменно принимает
значение — 1. Несмотря на последующее присваивание ей значения 100, она это зна-
чение теряет.
В правилах действия областей видимости есть одна деталь: хотя блоки могут быть
вложенными, ни одна переменная, объявленная во внутренней области видимости, не
может иметь имя, совпадающее с именем переменной, объявленной во внешней об-
ласти видимости. Например, следующая программа из-за попытки объявить две от-
дельные переменные с одинаковыми именами скомпилирована не будет.
/*Здесь делается попытка объявить переменную во
внутренней области видимости с таким же именем, как у
переменной, определенной во внешней области видимости.
*** Эта программа не будет скомпилирована. ***
*/using System;
class NestVar {
public static void Main() {
int count;
for(count = 0; count < 10; count = count+1) {
Console.WriteLine("This is count: " + count);
int count; // Неверно!!!
for(count = 0; count < 2; count++)
Console.WriteLine("В этой программе есть ошибка!");
Если вы до этого программировали на C/C++, вам должно быть известно, что на имена, объявляемые во внутренней области видимости, никакие ограничения не накладываются. Таким образом, в языках C/C++ объявление переменной count внутри блока внешнего цикла for было бы совершенно законным. Однако при всей своей законности такое объявление скрывает внешнюю переменную. Поэтому разработчики С#, зная, что подобное сокрытие имен может легко привести к ошибкам программирования, решили запретить его.
