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

  • Полный код .

  • Классы и объекты: конструкторы и деструктуры Цель работы

  • Классы и объекты: свойства. Инкапсуляция. Цель работы: Познакомиться с реализацией принципа инкапсуляции на языке С.Теория

  • Индивидуальные задания Задание 1 Разработать класс для представления объекта множество символов

  • Лаба 3. Лабораторная работа 4 Часть 1


    Скачать 190 Kb.
    НазваниеЛабораторная работа 4 Часть 1
    Дата01.11.2021
    Размер190 Kb.
    Формат файлаdoc
    Имя файлаЛаба 3.doc
    ТипЛабораторная работа
    #260306


    Лабораторная работа 4

    Часть 1



    Классы и объекты: общие сведения, поля, методы

    Цель работы:

    Познакомиться с основой объектного подхода в языке C#, созданием объектов и классов.

    Теория

    С теоретической точки зрения: класс – это тип, описывающий устройство объектов; поля – это переменные, принадлежащие классу; методы – это функции (процедуры), принадлежащие классу; объект – это экземпляр класса, сущность в адресном пространстве компьютера. Можно сказать, что класс является шаблоном для объекта, описывающим его структуру и поведение. Поля класса определяют структуру объекта, методы класса – поведение объекта, значение полей объекта – состояние объекта.

    С точки зрения практической реализации (в самом тексте программы) класс является типом данных, а объект – переменной этого типа.

    Методы и переменные, составляющие класс, называются членами класса. При определении класса объявляются данные, которые он содержит, и код, работающий с этими данными. Данные содержатся в переменных экземпляра, которые определены классом, а код содержится в методах. В С# определены несколько специфических разновидностей членов класса. Это — поля, константы, методы, конструкторы, деструкторы, индексаторы, события, операторы, свойства и вложенные типы.

    Классы объявляются с помощью ключевого слова class:
    [уровень доступа] class <имя класса>
    {

    1. Описание полей

    2. Описание методов

    3. Описание прочих членов класса

    }
    Уровней доступа для классов два: 1) public – доступ к классу возможен из любого места одной сборки либо из другой сборки, на которую есть ссылка; 2) internal – доступ к классу возможен только из сборки, в которой он объявлен. При объявлении класса модификатор доступа можно не указывать, при этом будет применяться режим по умолчанию internal.

    Класс следует объявлять внутри пространства имен namespace, но за пределами другого класса (исключение – вложенные типы). Классы содержат поля данных и объявления пользовательских процедур и функций, предназначенные для выполнения над объектами различных операций и которые обобщенно называют методами

    Поле – это переменная любого типа, которая объявлена непосредственно в классе. Описание полей делается следующим образом:

    <уровень доступа> <тип переменной> <имя переменной>;

    Метод представляет собой блок кода, содержащий набор инструкций, реализующих поведение экземпляров класса. В C# все инструкции выполняются в коде методов (в том числе метод Main, который является точкой входа для каждого приложения C# и вызывается при запуске программы).

    Описание метода осуществляется следующим образом:

    <уровень доступа> <возращаемый тип><имя метода > (<список параметров>){тело_метода}

    Для членов класса уровней доступа пять: 1) public – доступ к члену возможен из любого места одной сборки, либо из другой сборки, на которую есть ссылка; 2) protected – доступ к члену возможен только внутри класса, либо в классе-наследнике (при наследовании); 3) internal – доступ к члену возможен только из сборки, в которой он объявлен; 4) private – доступ к члену возможен только внутри класса; 5) protected internal - доступ к члену возможен из одной сборки, либо из класса-наследника другой сборки.

    Не указав модификатор доступа для члена, по умолчанию ему будет присвоен режим private.

    Пример 1.1 Объявление простейшего класса

    Задание.

    Объявите класс, который предназначен для операций с прямоугольником

    Решение.

    namespace MyConsoleApplication

    {

    // Объявление класса

    public class Rectangle

    {

    //Члены класса:

    //Поля.

    public int FSideA;

    public int FSideB;

    public string FName;

    // методы

    public int GetPerimeter ()

    {

    return (FSideA + FSideB) * 2;

    }

    public void SetName(string newName)

    {

    FName = newName; return true;

    }

    public string GetName()

    {

    return FName;

    }

    }

    }

    Чтобы от описания класса перейти к объекту, следует выполнить соответствующее объявление. Создание объекта осуществляется по мере востребованности работы с ним следующим образом:

    имя_класса имя_обьекта = new имя_класса();

    Пример 1.2 Создание объектов и работа с ними

    Задание.

    Создайте 2 объекта класса Rectangle: первый “Большой прямоугольник” со сторонами 5 и 10 см; второй “Маленький прямоугольник” со сторонами 2 и 3 см. Определите периметр данный

    Решение (для одной фигуры)

    class Program

    {

    static void Main(string[] args)

    {

    //Создание первого объекта на основе класса Rectangle

    Rectangle myRectangle1 = new Rectangle();

    //Установим значение полей

    myRectangle1.FSideA = 5;

    myRectangle1.FSideB = 10;

    //Вызовем метод

    //изменения названия фигуры

    myRectangle1.SetName("Большой прямоугольник");

    //определения периметра фигуры

    int Perimeter1 = myRectangle1.GetPerimeter();

    • Выведем

    • имя фигуры

    Console.WriteLine(myRectangle1.FName); // значение периметра

    Console.WriteLine(Perimeter1);

    Console.ReadKey();

    • Создание второго объекта на основе класса Rectangle

    Rectangle myRectangle2 = new Rectangle();

    • Установим значение полей

    myRectangle2.FSideA = 2;

    myRectangle2.FSideB = 3;

    • Вызовем метод

    • изменения названия фигуры

    myRectangle2.SetName("Большой прямоугольник");

    • определения периметра фигуры

    int Perimeter2 = myRectangle1.GetPerimeter();

    • Выведем

    • имя фигуры

    Console.WriteLine(myRectangle2.FName); // значение периметра

    Console.WriteLine(Perimeter2); Console.ReadKey();

    }

    }

    Задание для самостоятельной работы

    1. Приведите пример класса

    2. Для объявленного класса определите методы;

    3. Создайте несколько экземпляров класса и продемонстрируйте работу с ним.


    Полный код.

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    namespace MyConsoleApplication

    {

    // Объявление класса

    public class Rectangle

    {

    • Члены класса:

    • Поля.

    public int FSideA;

    public int FSideB;

    public string FName;

    // методы

    public int GetPerimeter ()

    {

    return (FSideA + FSideB) * 2;

    }

    public void SetName(string newName)

    {

    FName = newName;

    }

    public string GetName()

    {

    return FName;

    }

    class Program

    {

    static void Main(string[] args)

    {

    Console.WriteLine("Работа с первым объектом");

    • Создание первого объекта на основе класса Rectangle

    Rectangle myRectangle1 = new Rectangle();

    • Установим значение полей

    myRectangle1.FSideA = 5; myRectangle1.FSideB = 10;

    • Вызовем метод

    • изменения названия фигуры

    myRectangle1.SetName("Большой прямоугольник");

    • определения периметра фигуры

    int Perimeter1 = myRectangle1.GetPerimeter();

    • Выведем

    • имя фигуры

    Console.WriteLine(myRectangle1.FName); // значение периметра

    Console.WriteLine(Perimeter1); Console.ReadKey();

    Console.WriteLine("Работа со вторым объектом");

    • Создание второго объекта на основе класса Rectangle

    Rectangle myRectangle2 = new Rectangle();

    • Установим значение полей

    myRectangle2.FSideA = 2; myRectangle2.FSideB = 3;

    • Вызовем метод

    • изменения названия фигуры

    myRectangle2.SetName("Маленький прямоугольник");

    • определения периметра фигуры

    int Perimeter2 = myRectangle2.GetPerimeter();

    • Выведем

    • имя фигуры

    Console.WriteLine(myRectangle2.FName); // значение периметра

    Console.WriteLine(Perimeter2); Console.ReadKey();

    }

    }

    Часть 2



    Классы и объекты: конструкторы и деструктуры

    Цель работы:

    Познакомиться с основой объектного подхода в языке C#, использованием конструкторов и деструкторов.

    Теория

    Каждый раз, когда создается экземпляр класса вызывается специальный метод – конструктор. Конструкторы позволяют программисту задавать значения по умолчанию, ограничивать число установок и писать код, который является гибким и удобным для чтения. Класс может иметь несколько конструкторов, принимающих различные аргументы. Конструкторы имеют то же имя, что и класс. Конструкторы вызывают с помощью оператора new. Конструктор не возвращает значение, даже типа void. Конструктор без параметров называется конструктором по умолчанию. Если конструктор в классе явным образом не задан, компилятор C# для обеспечения создания экземпляров класса, предоставляет открытый конструктор по умолчанию (в этом случае все поля экземпляра класса инициализируются значениями по умолчанию, принятыми для переменных).

    Конструктор может использовать ключевое слово base для вызова конструктора базового класса.

    Конструкторы могут быть отмечены модификаторами public (открытый), private (закрытый), protected (защищенный), internal (внутренний) или protectedinternal (защищенный внутренний). Эти модификаторы доступа определяют порядок доступа пользователей класса к конструкторам класса.

    Пример 2.1 Работа с конструкторами

    Задание.

    Создайте два конструктора: конструктор по умолчанию (прямоугольник 1х1) и конструктор, принимающий аргументы (большой прямоугольник 5х10). Определите периметр фигуры и выведите название фигуры и её периметр на экран.
    Решение.

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    namespace MyConsoleApplication

    {

    // Объявление класса

    public class Rectangle

    {

    • Члены класса:

    • Поля.

    public int FSideA;

    public int FSideB;

    public string FName;

    • Конструкторы

    • Конструктор по умолчанию

    public Rectangle()

    {

    FSideA = 1; FSideB = 1;

    FName = "Прямоугольник 1х1";

    }

    • Конструктор с аргументами

    public Rectangle(string Name, int SideA, int SideB)

    {

    FSideA = SideA;

    FSideB = SideB; FName = Name;

    }

    // методы

    public int GetPerimeter ()

    {

    return (FSideA + FSideB) * 2;

    }

    public void SetName(string newName)

    {

    FName = newName;

    }

    public string GetName()

    {

    return FName;

    }

    }

    class Program

    {

    static void Main(string[] args)

    {

    Console.WriteLine("Работа с первым объектом");

    // Создание первого объекта на основе класса Rectangle (Большой прямоугольник со сторонами 5 и 10)

    Rectangle myRectangle1 = new Rectangle("Большой прямоугольник",5,10);

    • Вызовем метод

    • определения периметра фигуры

    int Perimeter1 = myRectangle1.GetPerimeter();

    • Выведем

    • имя фигуры

    Console.WriteLine(myRectangle1.FName);

    // значение периметра

    Console.WriteLine(Perimeter1); Console.ReadKey();

    // Создание второго объекта на основе класса Rectangle (малый прямоугольник)

    Rectangle myRectangle2 = new Rectangle();

    • Вызовем метод

    • определения периметра фигуры

    int Perimeter2 = myRectangle2.GetPerimeter();

    • Выведем

    • имя фигуры

    Console.WriteLine(myRectangle2.FName); // значение периметра

    Console.WriteLine(Perimeter2); Console.ReadKey();

    }

    }

    }

    Реализация для одного класса нескольких конструкторов является примером полиморфизма. Полиморфизм – механизм, позволяющий использовать одно имя для реализации схожих, но технически разных задач. Целью полиморфизма, применительно к объектно-ориентированному программированию, является использование одного имени для задания общих для класса действий. В более общем смысле, в основе полиморфизма лежит идея «использовать один интерфейс для множества методов». Для компилятора полиморфные функции должны различаться принимаемыми параметрами. Это различие может быть по их количеству или по их типам.

    Наследование – это процесс, посредством которого один объект может наследовать основные свойства другого объекта и добавлять к ним черты, характерные только для него. Наследование является важным, поскольку оно позволяет поддерживать концепцию иерархии классов (hierarchical classification). Применение иерархии классов делает управляемыми большие потоки информации. Без использования иерархии классов, для каждого объекта пришлось бы задать все характеристики, которые бы исчерпывающи его определяли.

    Однако при использовании наследования можно описать объект путем определения того общего класса (или классов), к которому он относится, но со специальными чертами, делающие объект уникальным.

    Синтаксис наследования следующий: при описании класса-потомка его класс-предок указывается через двоеточие. Пример определения класса-предка Dad и класса-потомка Son:

    public class Dad {}

    public class Son: Dad {}

    При инициализации полей объектов класса-наследника необходимо также инициализировать и поля базового класса. Инициализация полей, как было сказано выше, обычно осуществляется с использованием конструктора. Передача управления конструктору базового класса при создании объекта – представителя производного класса осуществляется посредством конструкции ...(...):base(...){...}, которая располагается в объявлении конструктора класса наследника между заголовком конструктора и телом. После ключевого слова base в скобках располагается список значений параметров конструктора базового класса. Очевидно, что выбор соответствующего конструктора определяется типом значений в списке (возможно, пустом) параметров.

    Пример:

    public class Dad { int a; public Dad(int s); }

    public class Son: Dad { public Son(int k):base(k) {} }

    Если же у базового класса не объявлено ни одного конструктора (оставлен конструктор по умолчанию) или объявлен конструктор без параметров, тогда конструкцию base можно не использовать: при ее отсутствии управление передается конструктору без параметров. Однако при вызове конструктора можно передавать управление не только конструктору базового класса, но и другому конструктору данного класса. Это удобно в тех случаях, когда необходимо создать множество объектов, различающихся между собой каким-либо образом, но и имеющим некую общую часть. Тогда для реализации общей части можно написать какой-то общий конструктор, а уже в других конструкторах, выполняющих более детальную настройку объекта, вызывать общий. Передача управления собственному конструктору аналогична описанной выше, только вместо ключевого слова base используется ключевое слово this.

    Пример:

    public class Dad { int a; 12 public Dad(int s); }

    public class Son: Dad {

    public Son(int k):base(k) {}

    public Son():this(10) {} }

    Копирующий конструктор (copy constructor) создает новый объект, копируя переменные из существующего объекта того же типа. Пусть, например, требуется передать объект Time конструктору Time() так, чтобы новый объект Time содержал те же значения, что и старый. Язык С# не добавляет в класс копирующий конструктор, так что программист должен написать такой конструктор самостоятельно. Подобный конструктор всего лишь копирует элементы исходного объекта во вновь создаваемый:

    public Time(Time existingTimeObject)

    {

    Year = existingTimeObject.Year;

    Montn = existingTimeObject.Month;

    Date = existingTimeObject.Date;

    HOLT = existingTimeObject.HOLT;

    Minute = existingTimeObject.Minute;

    Second = existinqTimeObject.Second;

    }

    Копирующий конструктор вызывается путем создания объекта типа Time и передачи ему имени копируемого объекта Time:

    Time t3= new Time (t2);

    Здесь переменная t2 передается в качестве аргумента existingTimeQbject копируещему конструктору, который создаст новый объект Time
    Ключевое слово this

    Ключевое слово this является ссылкой на текущий экземпляр объекта. Ссылка This (иногда ее называют указателем) является скрытым указателем на каждый нестатический метод класса. Любой метод может использовать ключевое слово this для доступа к другим нестатическим методам и переменным этого объекта. Существует три типичных случая применения ссылки this. Первый доступ к члену объекта, скрытому параметром. Вторым применением ссылки this является передача ссылки на текущий объект другому методу в качестве аргумента. Например, в следующем коде:

    public void FirstMetnod(OtherClass otherQbiect)

    {

    otherQbject.SecondMethod(this);

    }

    используются два класса: один с методом First Method (), а другой, класс OtherClass, с методом SecondMethod(). В теле FirstMethod() вызывается метод SecondMethod(), которому передается текущий объект для дальнейшей обработки. Третье применение ссылки this связано с индексаторами.
    Деструктор – метод, используемый для уничтожения экземпляров классов.

    Класс может иметь только один деструктор. Деструкторы не могут наследоваться или перегружаться. Деструкторы невозможно вызвать: они запускаются автоматически (момент вызова определяется сборщиком мусора) или вызываются при выходе из программы. Деструктор не принимает модификаторы и не имеет параметров. Они имеют то же имя, что и класс, но с добавление слева имени символа «»
    Пример. Работа деструкторов

    Дополните класс Rectangle деструктором. Продемонстрируйте его работу.

    Решение.



    • Конструкторы

    • Конструктор по умолчанию


    // Конструктор с аргументами



    • Деструктор

    Rectangle()

    {

    System.Diagnostics.Trace.WriteLine(this.GetName() + " уничтожен");

    }

    • методы


    Статические поля – поля, принадлежащие классу. Они объявляются с ключевым словом static. Основное отличие от обычных полей – для обращения к статическим полям не требуется создание объекта. Доступ осуществляется напрямую через имя класса. Более того, через объекты к статическим полям обратиться нельзя. Пример объявления статического поля:

    public static int I;
    Параметризованные классы – классы, позволяющие определить тип своих аргументов при непосредственном создании объектов.

    Пример параметризованного класса:


    Основное ограничение, налагаемое на параметризованные классы при их создании: необходимо следить, чтобы операции, используемые для типа параметра, были определены для всех типов или же использовать механизмы преобразования типов.

    Задание для самостоятельной работы

    1. Для вашего примера разработайте родительский класс и класс наследник.

    2. Дополните классы конструктором по умолчанию и конструктором, принимающим аргументы. При этом конструктор дочернего класса должен ссылаться на конструктор родительского класса или на свой другой конструктор.

    3. Дополните класс статическим полем.

    4. Дополните класс полем – экземпляром параметризованного класса.

    5. Дополните класс деструктором.

    6. Написать демонстрационную программу, в которой создаются и разрушаются объекты пользовательского класса и каждый вызов конструктора и деструктора сопровождается выдачей соответствующего сообщения (какой объект, какой конструктор или деструктор вызван).



    Часть 3


    Классы и объекты: свойства. Инкапсуляция.

    Цель работы:

    Познакомиться с реализацией принципа инкапсуляции на языке С#.

    Теория

    Инкапсуляция – один из основных принципов объектно-ориентированного программирования. Согласно принципу инкапсуляции, класс может задать уровень доступности каждого из членов по отношению к коду вне класса. Методы и поля, которые не предназначены для использования вне класса или сборки, могут быть скрыты, с целью ограничения потенциальной угрозы возникновения ошибок программного кода или его вредоносное использование.

    Реализация принципа инкапсуляции обеспечивается за счет:

    1) использования спецификаторов доступа для каждого члена класса;

    2) использования свойств.

    Свойства служат для организации упорядоченного доступа к полям класса. Как правило, свойство связано с закрытым полем класса и определяет методы его получения и установки.

    Синтаксис свойства:

    <уровень доступа> <тип><имя свойства > { get { код_доступа} set { код_доступа} }

    Значения спецификаторов для свойств и методов аналогичны. Чаще всего свойства объявляются как открытые (со спецификатором (уровнем доступа) public), поскольку они входят в интерфейс объекта. Код доступа представляет собой блоки операторов, которые выполняются при получении (get) или установке (set) свойства. Может отсутствовать либо часть get, либо set, но не обе одновременно.

    Если отсутствует часть set, свойство доступно только для чтения (read-only), если отсутствует часть get, свойство доступно только для записи (write-only). Метод записи обычно содержит действия по проверке допустимости устанавливаемого значения, метод чтения может содержать, например, поддержку счетчика обращений к полю.

    В программе свойство выглядит как поле класса. При обращении к свойству автоматически вызываются указанные в нем методы чтения и установки. Синтаксически чтение и запись свойства выглядят почти как методы. Метод get должен содержать оператор return, возвращающий выражение, для типа которого должно существовать неявное преобразование к типу свойства. В методе set используется параметр со стандартным именем value, который содержит устанавливаемое значение. Вообще говоря, свойство может и не связываться с полем. Фактически, оно описывает один или два метода, которые осуществляют некоторые действия над данными того же типа, что и свойство. В отличие от открытых полей, свойства обеспечивают разделение между внутренним состоянием объекта и его интерфейсом и, таким образом, упрощают внесение изменений в класс.

    Таким образом, свойство — это член, предоставляющий гибкий механизм для чтения, записи или вычисления значения частного (private) поля.
    Задание.

    Создайте объект класса Rectangle: “Большой прямоугольник” со сторонами 5 и 10 см; объявите все поля класса как закрытые; организуйте доступ к полям через свойства: Периметр (только для чтения) и Имя (для чтения и записи).

    Решение.
    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;
    namespace MyConsoleApplication

    {

    // Объявление класса

    public class Rectangle

    {

    • Члены класса:

    • Поля.

    private int FSideA;

    private int FSideB;

    private string FName;

    // Конструктор с аргументами

    public Rectangle(string Name, int SideA, int SideB)

    {

    FSideA = SideA;

    FSideB = SideB;

    FName = Name;

    }

    • Свойства

    • Только для чтения

    public int Perimeter

    { get {return (FSideA + FSideB) * 2;}

    }

    • Для чтения и для записи

    public string Name

    {

    set { FName=value; } get { return FName; }

    }

    }

    class Program

    {

    static void Main(string[] args)

    {

    // Создание объекта на основе класса Rectangle (Большой прямоугольник со сторонами 5 и 10)

    Rectangle myRectangle = new Rectangle("Большой прямоугольник",5,10);

    • Выведим свойства фигуры

    • имя

    Console.WriteLine(myRectangle.Name);

    // значение периметра

    Console.WriteLine(myRectangle.Perimeter); Console.ReadKey();

    }

    }

    }
    В производном классе можно определить член с таким же именем, как и у члена его базового класса. В этом случае член базового класса скрывается в производном классе. И хотя формально в C# это не считается ошибкой, компилятор все же выдаст сообщение, предупреждающее о том, что имя скрывается. Если член базового класса требуется скрыть намеренно, то перед его именем следует указать ключевое слово new, чтобы избежать появления подобного предупреждающего сообщения. Следует, однако, иметь в виду, что это совершенно отдельное применение ключевого слова new, не похожее на его применение при создании экземпляра объекта:
    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;
    namespace ConsoleApplication1

    {

    class MyClass

    {

    public int x = 10, y = 5, z = 6;

    }
    class ClassA : MyClass

    {

    // Скрываем члены класса MyClass

    public new int x = 12, y = -2, z = -5;

    }
    class ClassB : MyClass

    {

    public int x;

    }
    class Program

    {

    static void Main()

    {

    ClassA obj1 = new ClassA();

    ClassB obj2 = new ClassB();
    Console.WriteLine("Координаты объекта obj1: {0} {1} {2}",obj1.x,obj1.y,obj1.z);

    Console.WriteLine("Координаты объекта obj2: {0} {1} {2}", obj2.x, obj2.y, obj2.z);
    Console.ReadLine();

    }

    }

    }



    Имеется еще одна форма ключевого слова base, которая действует подобно ключевому слову this, за исключением того, что она всегда ссылается на базовый класс в том производном классе, в котором она используется. Ниже эта форма приведена в общем виде:

    base.член

    где член может обозначать метод или переменную экземпляра. Эта форма ключевого слова base чаще всего применяется в тех случаях, когда под именами членов производного класса скрываются члены базового класса с теми же самыми именами. С помощью ключевого слова base могут также вызываться скрытые методы. Давайте рассмотрим пример:

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;
    namespace ConsoleApplication1

    {

    class MyClass

    {

    public int x;

    }
    class ClassA : MyClass

    {

    new int x = 10;
    public void someMethod(int i1, int i2)

    {

    // Координата x из базового класса MyClass

    base.x = i1;

    Console.WriteLine("x (в базовом классе) = " + base.x);

    // Координата x из класса ClassA

    x = i2;

    Console.WriteLine("x (в производном классе) = " + x);

    }

    }
    class Program

    {

    static void Main()

    {

    ClassA obj1 = new ClassA();

    obj1.someMethod(1,25);

    Console.ReadLine();

    }

    }

    }
    C# является строго типизированным языком программирования. Помимо стандартных преобразований и автоматического продвижения простых типов значений, в этом языке строго соблюдается принцип совместимости типов. Это означает, что переменная ссылки на объект класса одного типа, как правило, не может ссылаться на объект класса другого типа.

    Вообще говоря, переменная ссылки на объект может ссылаться только на объект своего типа.

    Но из этого принципа строгого соблюдения типов в C# имеется одно важное исключение: переменной ссылки на объект базового класса может быть присвоена ссылка на объект любого производного от него класса. Такое присваивание считается вполне допустимым, поскольку экземпляр объекта производного типа инкапсулирует экземпляр объекта базового типа. Следовательно, по ссылке на объект базового класса можно обращаться к объекту производного класса:
    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;
    namespace ConsoleApplication1

    {

    class ClassA

    {

    public int a;
    public ClassA(int i)

    {

    a = i;

    }

    }
    class ClassB : ClassA

    {

    public int b;
    public ClassB(int r, int i)

    : base(i)

    {

    b = r;

    }

    }
    class ClassC

    {

    public int a;
    public ClassC(int i)

    {

    a = i;

    }

    }
    class Program

    {

    static void Main()

    {

    ClassA objA1 = new ClassA(10);

    ClassA objA2 = new ClassA(5);
    // Присваивание однотипных объектов правильно:

    objA2 = objA1;
    ClassB objB = new ClassB(8, 9);

    // Присваивание объекта, имеющего тип унаследованного класса допускается:

    objA1 = objB;

    // Так нельзя

    // objB = objA1;
    // Присваивать похожие, но не связанные друг с другом

    // принципом наследования объекты нельзя

    ClassC objC = new ClassC(8);

    // objC = objA1;
    Console.ReadLine();

    }

    }

    }
    Следует особо подчеркнуть, что доступ к конкретным членам класса определяется типом переменной ссылки на объект, а не типом объекта, на который она ссылается. Это означает, что если ссылка на объект производного класса присваивается переменной ссылки на объект базового класса, то доступ разрешается только к тем частям этого объекта, которые определяются базовым классом. И в этом есть своя логика, поскольку базовому классу ничего не известно о тех членах, которые добавлены в производный от него класс.

    Один из самых важных моментов для присваивания ссылок на объекты производного класса переменным базового класса наступает тогда, когда конструкторы вызываются в иерархии классов. Как вам должно быть уже известно, в классе нередко определяется конструктор, принимающий объект своего класса в качестве параметра. Благодаря этому в классе может быть сконструирована копия его объекта.
    Задание для самостоятельной работы

    1. Дополните класс свойствами разных видов (только для чтения, только для записи, для записи и для чтения).

    2. Дополните класс примером скрытия члена базового класса. Продемонстрируйте как образом из потомка можно обратиться к скрытым полям и методам.

    3. Продемонстрируйте для вашего класса пример совместимости типов.



    Индивидуальные задания

    Задание 1

    1. Разработать класс для представления объекта множество символов. Определить конструктор с одним параметром-строкой, который задаёт элементы множества и который можно использовать как конструктор умолчания. Определить конструктор, который копирует в новое множество элементы другого множества, не превышающие заданное значение, который можно использовать как конструктор копирования. Определить деструктор. Определить преобразования из переменной типа char в множество и из множества в переменную типа char.

    2. Разработать класс для представления объекта строка. Определить конструктор с одним параметром целого типа – длина строки, который можно использовать как конструктор умолчания. Определить конструктор, который копирует в новую строку n первых символов другой строки и который можно использовать как конструктор копирования. Определить деструктор. Определить преобразования из вещественного числа в строку, представляющую это число, и из строки в вещественное число.

    3. Разработать класс для представления объекта матрица, состоящая из элементов типа char. Определить конструктор с двумя параметрами целого типа – размерность матрицы, который можно использовать как конструктор умолчания. Определить конструктор, который создаёт новую матрицу таким образом, что все её элементы больше элементов другой матрицы на заданное число, и который можно использовать как конструктор копирования. Определить деструктор. Определить преобразования из переменной типа char в матрицу – заполнение матрицы и из матрицы в переменную типа double – среднее арифметическое элементов матрицы.

    4. Разработать класс для представления объекта матрица, состоящая из элементов типа unsigned char. Определить конструктор с двумя параметрами целого типа – размерность матрицы, который можно использовать как конструктор умолчания. Определить конструктор, который создаёт новую матрицу таким образом, что все её элементы больше элементов другой матрицы на заданное число, и который можно использовать как конструктор копирования. Определить деструктор. Определить преобразования из переменной типа unsigned char в матрицу – заполнение матрицы и из матрицы в переменную типа double – среднее арифметическое элементов матрицы.

    5. Разработать класс для представления объекта матрица, состоящая из элементов типа short int. Определить конструктор с двумя параметрами целого типа – размерность матрицы, который можно использовать как конструктор умолчания. Определить конструктор, который создаёт новую матрицу таким образом, что все её элементы больше элементов другой матрицы на заданное число, и который можно использовать как конструктор копирования. Определить деструктор. Определить преобразования из переменной типа short int в матрицу – заполнение матрицы и из матрицы в переменную типа double – среднее арифметическое элементов матрицы.

    6. Разработать класс для представления объекта матрица, состоящая из элементов типа long int. Определить конструктор с двумя параметрами целого типа – размерность матрицы, который можно использовать как конструктор умолчания. Определить конструктор, который создаёт новую матрицу таким образом, что все её элементы больше элементов другой матрицы на заданное число, и который можно использовать как конструктор копирования. Определить деструктор. Определить преобразования из переменной типа long int в матрицу – заполнение матрицы и из матрицы в переменную типа double – среднее арифметическое элементов матрицы.

    7. Разработать класс для представления объекта матрица, состоящая из элементов типа double. Определить конструктор с двумя параметрами целого типа – размерность матрицы, который можно использовать как конструктор умолчания. Определить конструктор, который создаёт новую матрицу таким образом, что все её элементы больше элементов другой матрицы на заданное число, и который можно использовать как конструктор копирования. Определить деструктор. Определить преобразования из переменной типа double в матрицу – заполнение матрицы и из матрицы в переменную типа double – среднее арифметическое элементов матрицы.

    8. Разработать класс для представления объекта множество символов. Определить конструктор с одним параметром-строкой, который задаёт элементы множества и который можно использовать как конструктор умолчания. Определить конструктор, которые копирует в новое множество элементы другого множества, не превышающие заданное значение, который можно использовать как конструктор копирования. Определить деструктор. Определить преобразования из переменной типа char в множество и из множества в переменную типа char.

    9. Разработать класс для представления объекта строка. Определить конструктор с одним параметром целого типа – длина строки, который можно использовать как конструктор умолчания. Определить конструктор, который копирует в новую строку n первых символов другой строки и который можно использовать как конструктор копирования. Определить деструктор. Определить преобразования из вещественного числа в строку, представляющую это число, и из строки в вещественное число.

    10. Разработать класс для представления объекта матрица, состоящая из элементов типа char. Определить конструктор с двумя параметрами целого типа – размерность матрицы, который можно использовать как конструктор умолчания. Определить конструктор, который создаёт новую матрицу таким образом, что все её элементы больше элементов другой матрицы на заданное число, и который можно использовать как конструктор копирования. Определить деструктор. Определить преобразования из переменной типа char в матрицу – заполнение матрицы и из матрицы в переменную типа double – среднее арифметическое элементов матрицы.

    11. Разработать класс для представления объекта матрица, состоящая из элементов типа unsigned char. Определить конструктор с двумя параметрами целого типа – размерность матрицы, который можно использовать как конструктор умолчания. Определить конструктор, который создаёт новую матрицу таким образом, что все её элементы больше элементов другой матрицы на заданное число, и который можно использовать как конструктор копирования. Определить деструктор. Определить преобразования из переменной типа unsigned char в матрицу – заполнение матрицы и из матрицы в переменную типа double – среднее арифметическое элементов матрицы.

    12. Разработать класс для представления объекта матрица, состоящая из элементов типа short int. Определить конструктор с двумя параметрами целого типа – размерность матрицы, который можно использовать как конструктор умолчания. Определить конструктор, который создаёт новую матрицу таким образом, что все её элементы больше элементов другой матрицы на заданное число, и который можно использовать как конструктор копирования. Определить деструктор. Определить преобразования из переменной типа short int в матрицу – заполнение матрицы и из матрицы в переменную типа double – среднее арифметическое элементов матрицы.

    13. Разработать класс для представления объекта матрица, состоящая из элементов типа long int. Определить конструктор с двумя параметрами целого типа – размерность матрицы, который можно использовать как конструктор умолчания. Определить конструктор, который создаёт новую матрицу таким образом, что все её элементы больше элементов другой матрицы на заданное число, и который можно использовать как конструктор копирования. Определить деструктор. Определить преобразования из переменной типа long int в матрицу – заполнение матрицы и из матрицы в переменную типа double – среднее арифметическое элементов матрицы.

    14. Разработать класс для представления объекта матрица, состоящая из элементов типа double. Определить конструктор с двумя параметрами целого типа – размерность матрицы, который можно использовать как конструктор умолчания. Определить конструктор, который создаёт новую матрицу таким образом, что все её элементы больше элементов другой матрицы на заданное число, и который можно использовать как конструктор копирования. Определить деструктор. Определить преобразования из переменной типа double в матрицу – заполнение матрицы и из матрицы в переменную типа double – среднее арифметическое элементов матрицы.


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