- •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. Операторы условного перехода. Примеры применений.
Void iProps.Prop3() { Console.WriteLine("Свойство 3 интерфейса 1"); }
Void iPropsOne.Prop3() { Console.WriteLine("Свойство 3 интерфейса 2"); }
public void Prop3FromInterface1() { ((IProps)this).Prop3(); }
public void Prop3FromInterface2() { ((IPropsOne)this).Prop3(); }}
Для первого из методов с совпадающей сигнатурой выбрана стратегия склеивания, так что в классе есть только один метод, реализующий методы двух интерфейсов. Методы с разной сигнатурой реализованы двумя перегруженными методами класса. Для следующей пары методов с совпадающей сигнатурой выбрана стратегия переименования. Методы интерфейсов реализованы как закрытые методы, а затем в классе объявлены два новых метода с разными именами, являющиеся обертками закрытых методов класса.
Наследование от общего предка
Проблема наследования от общего предка характерна, в первую очередь, для множественного наследования классов. Если класс C является наследником классов A и B, а те, в свой черед, являются наследниками класса Parent, то класс наследует свойства и методы своего предка Parent дважды, один раз получая их от класса A, другой от — B. Это явление называется еще дублирующим наследованием. Для классов ситуация осложняется тем, что классы A и B могли по-разному переопределить методы родителя и для потомков предстоит сложный выбор реализации.
Для интерфейсов сама ситуация дублирующего наследования маловероятна, но возможна, поскольку интерфейс, как и любой класс, может быть наследником другого интерфейса. Поскольку у интерфейсов наследуются только сигнатуры, а не реализации, как в случае классов, то проблема дублирующего наследования сводится к проблеме коллизии имен. По-видимому, естественным решением этой проблемы в данной ситуации является склеивание, когда методам, пришедшим разными путями от одного родителя, будет соответствовать единая реализация.
21. Структуры (struct) и перечисления (enum). Отличия структур от классов.
Как вы уже знаете, классы — это ссылочные типы. Это означает, что к объектам классов доступ осуществляется через ссылку. Этим они отличаются от типов значений, к которым в С# реализован прямой доступ. Но иногда желательно получать прямой доступ и к объектам, как в случае нессылочных типов. Одна из причин для этого — эффективность. Ведь очевидно, что доступ к объектам классов через ссылки увеличивает расходы системных ресурсов, в том числе и памяти. Даже для очень маленьких объектов требуются существенные объемы памяти. Для компенсации упомянутых расходов времени и пространства в С# предусмотрены структуры. Структура подобна классу, но она относится к типу значений, а не к ссылочным типам. Структуры объявляются с использованием ключевого слова struct и синтаксически подобны классам. Формат записи структуры таков:
struct имя : интерфейсы { // объявления членов
Элемент имя означает имя структуры.
Структуры не могут наследовать другие структуры или классы. Структуры не могут использоваться в качестве базовых для других структур или классов. (Однако, подобно другим С#-типам, структуры наследуют класс object). Структура может реализовать один или несколько интерфейсов. Они указываются после имени структуры и отделяются запятыми. Как и у классов, членами структур могут быть методы, поля, индексаторы, свойства, операторные методы и события. Структуры могут также определять конструкторы, но не деструкторы. Однако для структуры нельзя определить конструктор по умолчанию (без параметров). Дело в том, что конструктор по умолчанию автоматически определяется для всех структур, и его изменить нельзя. Поскольку структуры не поддерживают наследования, члены структуры нельзя определять с использованием модификаторов abstract, virtual или protected.
Объект структуры можно создать с помощью оператора new, подобно любому объекту класса, но это не обязательно. Если использовать оператор new, вызывается указанный конструктор, а если не использовать его, объект все равно будет создан, но не инициализирован. В этом случае вам придется выполнить инициализацию вручную, рассмотрим пример использования структуры для хранения информации о книге.
// Демонстрация использования структуры.
using System;
// Определениеструктуры,
struct Book {
public string author;
public string title;
public int copyright;
public Book(string a, string t, int c) {
author = a;
title = t;
copyright = c;
// Демонстрируем использование структуры Book,
classStructDemo {
public static void Main() {
Book bookl = new Book("Herb Schildt",
"C# A Beginner's Guide", 2001); // Вызов явнозаданного конструктора.
Book book2 = new Book(); // Вызов конструктора по умолчанию.
Book ЬоокЗ; // Создание объекта без вызова конструктора.
Console.WriteLine(bookl.title + ", автор " + bookl.author + 11, (с) " + bookl. copyright );
Console.WriteLine();
if(book2.title == null)
Console.WriteLine("Член book2.title содержит null.");
// Теперь поместим в структуру book2 данные.
book2.title = "Brave New World";
book2.author = "Aldous Huxley";
book2.copyright = 1932;
Console.Write("Теперь структура book2 содержит:\n " ) ;
Console.WriteLine(book2.title + ", автор " + book2.author + ", (c) " + book2.copyright);
Console.WriteLine();
// Console.WriteLine(ЬоокЗ.title); // Ошибка: сначала необходима инициализация.
ЬоокЗ.title = "Red Storm Rising";
Console.WriteLine(ЬоокЗ.title); // Теперьвсе Ok!
Вот результаты выполнения этой программы:
С# A Beginner's Guide, автор Herb Schildt, (с) 2001
Член book2.title содержит null.
Теперь структура book2 содержит:
Brave New World, автор Aldous Huxley, (с) 1932
Red Storm Rising
Как видно из результатов выполнения этой программы, структура может быть создана либо с помощью оператора new, который вызывает соответствующий конструктор, либо простым объявлением объекта. При использовании оператора new поля структуры будут инициализированы, причем это сделает либо конструктор по умолчанию (он инициализирует все поля значениями по умолчанию), либо конструктор, определенный пользователем. Если оператор new не используется, как в случае объекта bоокЗ, созданный таким образом объект остается неинициализированным, и его поля должны быть установлены до начала использования.
При присваивании одной структуры другой создается копия этого объекта. Это — очень важное отличие struct-объекта от с lass-объекта. Как упоминалось выше, присваивая одной ссылке на класс другую, вы просто меняете объект, на который ссылается переменная, стоящая с левой стороны от оператора присваивания. А присваивая одной struct-переменной другую, вы создаете копию объекта, указанного с правой стороны от оператора присваивания. Рассмотрим, например, следующую программу:
// Копирование структуры.
using System;
// Определяемструктуру,
struct MyStruct { public int x; }
// Демонстрируем присваивание структуры,
class StructAssignment {
public static void Main() {
MyStruct a;
MyStruct b;
a.x = 10;
b.x = 20;
Console .WriteLine ("a.x {0}, b.x {I}11, a.x, b.x);
a - b;
b.x = 30;
Console.WriteLine("a.x {0}, b.x {1}", a.x, b.x);
Эта программа генерирует следующие результаты.
а . х 10, b . x 20
a . x 20, b . x 30
Как подтверждают результаты выполнения этой программы, после присваивания а = b; структурные переменные а и b по-прежнему не зависят одна от другой. Другими словами, переменная а никак не связана с переменной Ь, если не считать, что переменная а содержит копию значения переменной Ь. Будь а и b ссылками на классы, все обстояло бы по-другому. Рассмотрим теперь class-версию предыдущей программы.
// Копирование класса.
using System;
// Определяем класс,
class MyClass { public int x; }
// Теперь покажем присваивание объектов класса.
class ClassAssignment {
public static void Main() {
MyClass a = new MyClassO;
MyClass b = new MyClassO;
a.x = 10;
b.x = 20;
Console.WriteLine("a.x {0}, b.x {1}", a.x, b.x);
a = b;
b.x = 30;
Console.WriteLine("a.x {0}, b.x {1}", a.x, b.x);
Вот какие результаты получены при выполнении этой программы:
a . x 10, b . x 20
a . x 30, b . x 30
Как видите, после присваивания объекта b переменной а обе переменные ссылаются на один и тот же объект, т.е. на тот, на который изначально ссылалась переменная b.
Зачем нужны структуры вы могли бы выразить удивление, почему С# включает тип struct , если, казалось бы, он представляет собой "слаборазвитую" версию типа class. Ответ следует искать в эффективности и производительности. Поскольку структуры — это типы значений, они обрабатываются напрямую, а не через ссылки. Таким образом, тип struct не требует отдельной ссылочной переменной. Это означает, что при использовании структур расходуется меньший объем памяти. Более того, благодаря прямому доступу к структурам, при работе с ними не снижается производительность, что имеет место при доступе к объектам классов. Поскольку классы — ссылочные типы, доступ к их объектам осуществляется через ссылки. Такая косвенность увеличивает затраты системных ресурсов при каждом доступе. Структуры этим не страдают. В общем случае, если вам нужно хранить небольшую группу связанных данных, но не нужно обеспечивать наследование и использовать другие достоинства ссылочных типов, тип struct может оказаться более предпочтительным вариантом.
Перечисления
Перечисление (enumeration) — это множество именованных целочисленных констант. Ключевое слово enum объявляет перечислимый тип. Формат записи перечисления таков:
enum имя {список_перечисления);
Здесь с помощью элемента имя указывается имя типа перечисления. Элемент список_перечисления представляет собой список идентификаторов, разделенных запятыми.
Рассмотрим пример. В следующем фрагменте кода определяется перечисление
apple, которое содержит список названий различных сортов яблок. I enum apple { Jonathan, GoldenDel, RedDel, Winsap, Cortland, Mclntosh } ;
Здесь важно понимать, что каждый символ списка перечисления означает целое число, причем каждое следующее число (представленное идентификатором) на единицу больше предыдущего. Поскольку значение первого символа перечисления равно нулю, следовательно, идентификатор Jonathan имеет значение 0, GoldenDel — значение 1 и т.д.
Константу перечисления можно использовать везде, где допустимо целочисленное значение. Однако между типом enum и встроенным целочисленным типом неявные преобразования не определены, поэтому при необходимости должна использоваться явно заданная операция приведения типов. В случае преобразования одного типа перечисления в другой также необходимо использовать приведение типов.
К членам перечисления доступ осуществляется посредством имени типа и оператора "точка". Например, при выполнении инструкции
I Console.WriteLine(apple.RedDel + " имеет значение " + I (int)apple.RedDel);
будет отображено следующее.
