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

  • Практическая работа № 1.13. Определение операций в классе

  • Унарные операции Можно определять в классе следующие унарные операции

  • Ход работы Задание1.

  • Бинарные операции

  • Задание 2. Определение операции сложения для класса SafeArray

  • Операции преобразования типа

  • Методические указания по выполнению лабораторных и практических работ по мдк


    Скачать 3.25 Mb.
    НазваниеМетодические указания по выполнению лабораторных и практических работ по мдк
    Дата23.01.2023
    Размер3.25 Mb.
    Формат файлаpdf
    Имя файла37._MU_PZ_PM.01_MDK_01.01_Razrabotka_programmnyx_moduley(1)_remo.pdf
    ТипМетодические указания
    #899980
    страница7 из 24
    1   2   3   4   5   6   7   8   9   10   ...   24
    Ход работы
    Задание. Пусть определены 3 класса, один из которых является базовым для двух других:
    Type

    54
    Tperson=class {базовый класс} fname:string; constructor Create(name:string); function info:string; virtual; end;
    Tstud=class(Tperson) {класс– потомок} fgr:integer; {поле для номера группы} constructor Create(name:string;gr:integer); function info:string; override; end;
    Tprof=class(Tperson) {класс– потомок} fdep:string; ; {поле для названия кафедры} constructor Create(name:string; dep:string); function info:string; override; end;
    В каждом из этих классов определен метод info. В базовом классе при помощи директивы virtual метод info объявлен виртуальным. Это дает возможность классу–потомку произвести замену виртуального метода своим собственным. В каждом классе–потомке определен свой метод info, который замещает соответствующий метод родительского класса и отмечается директивой override.
    Определим метод info для каждого класса индивидуально: function Tperson.info:string; begin result:=’’; end; function Tstud.info:string; begin result:=fname+' gruppa '+inttostr(fgr); end; function Tprof.info:string;

    55 begin result:=fname+' department '+fdep; end;
    Далее в программе список всех людей можно представить массивом объектов класса
    Tperson. Отметим, что объект – указатель.
    Список людей имеет вид: list: array[1..szl] of Tperson; { szl –размер списка}
    Объявить подобным образом список можно потому, что OP позволяет присвоить указателю на родительский класс значение указателя на класс– потомок. Поэтому элементами массива list могут быть как объекты класса Tstud, так и объекты класса Tprof.
    Вывод списка можно осуществить применением метода info к элементам массива, например:
    St:= ’’; for i:=1 to szl do if list[i]<>nil then
    St:=St+list[i].info+#13;
    ShowMessage('Spisok:'+#13+St); { вывод в окно сообщения}
    Во время работы программы каждый элемент массива может содержать как объект типа
    Tstud, так и объект типа Tprof.
    Концепция полиморфизма обеспечивает применение к объекту именно того метода info, который соответствует типу объекта.
    Напишем программу, которая использует объявления классов Tperson, Tstud, Tprof, формирует список студентов и преподавателей и выводит полученный список в окно сообщения.
    Будем использовать визуальное программирование.
    Окно формы будет иметь вид:
    GroupBox1—это компонент , объединяющий группу компонентов, связанных по смыслу.
    В данном случае он включает 2 зависимых переключателя – RadioButton1 и RadioButton2
    Текст модуля кода программы: unit Polimorfizm; interface uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls;
    Type
    TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Edit1: TEdit;
    Edit2: TEdit;
    GroupBox1: TGroupBox;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;

    56
    Button1: TButton;
    Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private
    { Private declarations } public
    { Public declarations } end; type Tperson=class fname:string; constructor Create(name:string); function info:string; virtual; end;
    Tstud=class(Tperson) {класс– потомок} fgr:integer; {поле для номера группы} constructor Create(name:string;gr:integer); function info:string; override; end;
    Tprof=class(Tperson) {класс– потомок} fdep:string; ; {поле для названия кафедры} constructor Create(name:string; dep:string); function info:string; override; end;
    Сonst szl=10;
    Var
    Form1: TForm1; list:array[1..szl] of Tperson; n:integer; implementation {исполняемая часть}
    {$R *.DFM} constructor Tperson.Сreate(name:string); {описание конструктора} begin fname:=name; end; constructor Tstud.Create(name:string;gr:integer); begin inherited create(name); fgr:=gr; end; constructor Tprof.Create(name:string;dep:string); begin inherited create(name); fdep:=dep; end; function Tperson.info:string; begin result:=fname; end; function Tstud.info:string; begin result:=fname+' gruppa '+inttostr(fgr); end; function Tprof.info:string; begin result:=fname+' department '+fdep;

    57 end; procedure TForm1.Button1Click(Sender: TObject);
    //процедура обработки нажатия на кнопку «Добавить» begin if nShowMessage('Spisok zapolnen'); end; prcedure TForm1.Button2Click(Sender: TObject);
    //процедура обработки нажатия на кнопку «Список»
    Var i:integer;
    St:string;
    Begin for i:=1 to szl do if list[i]<>nil then
    St:=St+list[i].info+#13;
    // list[i].info вызовет тот метод info, которому соответствует элемент
    ShowMessage('Spisok:'+#13+St); end; end.
    Процедура TForm1.Button1Click, которая запускается нажатием кнопки «Добавить» создает объект list[n] класса либо Tstud, либо Tprof.
    Класс создаваемого объекта определяется состоянием переключателя RadioButton.
    Установка переключателя в положение Студент определяет класс Tstud, а в положение –
    Преподаватель определяет класс Tprof. Процедура TForm1.Button2Click, которая запускается нажатием кнопки Список (Button2) применяет метод info к каждому элементу массива list[i] как к объекту списка и формирует строку, представляющую весь итоговый список.
    Виртуальность метода info обеспечивает применение к объекту именно того метода info, который соответствует типу объекта.
    Отметим, что в данной программе результаты выводятся в окно сообщения процедурой
    ShowMessage. Например:
    Showmessage('Spisok:'+#13+st);
    Showmessage('spisok zapolnen');
    Практическая работа № 1.13. Определение операций в классе
    Цель работы: изучить способы определения операций в классе
    Теоретический материал
    Операции класса
    C# позволяет переопределить действие большинства операций так, чтобы при использовании с объектами конкретного класса они выполняли заданные функции. Это дает возможность применять экземпляры собственных типов данных в составе выражений таким же образом, как стандартных, например:
    MyObject а, Ь, с; с = а + Ь; // используется операция сложения для класса MyObject

    58
    Определение собственных операций класса часто называют перегрузкой опера-
    ций. Перегрузка обычно применяется для классов, описывающих математические или физические понятия, то есть таких классов, для которых семантика операций делает программу более понятной. Если назначение операции интуитивно не понятно с первого взгляда, перегружать такую операцию не рекомендуется.
    Операции класса описываются с помощью методов специального вида(функций-
    операций). Перегрузка операций похожа на перегрузку обычных методов. Синтаксис операции:
    [ атрибуты ] спецификаторы объявитель_операции тело
    Атрибуты рассматриваются позже, в качествеспецификаторов одновременно используются ключевые словаpublicиstatic. Кроме того, операцию можно объявить как внешнюю
    (extern).
    Объявитель операции содержит ключевое словоoperator, по которому и опознается описание операции в классе.Тело операции определяет действия, которые выполняются при использовании операции в выражении. Тело представляет собой блок, аналогичный телу других методов.
    Новые обозначения для собственных операций вводить нельзя. Для операций класса сохраняются количество аргументов, приоритеты операций и правила ассоциации (справа налево или слева направо), используемые в стандартных типах данных.
    При описании операций необходимо соблюдать следующие правила:

    операция должна быть описана как открытый статический метод класса (спецификаторы public static);

    параметры в операцию должны передаваться по значению (то есть не должны предваряться ключевыми словами refилиout);

    сигнатуры всех операций класса должны различаться;

    типы, используемые в операции, должны иметь не меньшие права доступа, чем сама операция (то есть должны быть доступны при использовании операции).
    В С# существуют три вида операций класса: унарные, бинарные и операции пре- образования типа.
    Унарные операции
    Можно определять в классе следующие унарные операции:
    + - ! - ++ -- true false
    Синтаксис объявителя унарной операции: тип operator унарная_операция ( параметр )
    Примеры заголовков унарных операций: public static int operator+ ( MyObject m ) public static MyObject operator-- ( MyObject m ) public static bool operator true( MyObject m )
    Параметр, передаваемый в операцию, должен иметь тип класса, для которого она определяется. Операция должна возвращать:

    для операций +,-,! и - величину любого типа;

    для операций ++и--величину типа класса, для которого она определяется;

    для операций trueиfalseвеличину типа bool.
    Операции не должны изменять значение передаваемого им операнда. Операция, возвращающая величину типа класса, для которого она определяется, должна создать новый объект этого класса, выполнить с ним необходимые действия и передать его в качестве результата.
    Префиксный и постфиксный инкременты не различаются (для них может существовать только одна реализация, которая вызывается в обоих случаях).
    Операции trueиfalseобычно определяются для логических типов SQL, обладающих неопределенным состоянием, и не входят в число тем, рассматриваемых здесь.
    В качестве примера усовершенствуем приведенный в листинге 1.17классSafeArrayдля удобной и безопасной работы с массивом. В класс внесены следующие изменения:

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

    добавлена операция инкремента;

    добавлен вспомогательный метод Print вывода массива;

    59

    изменена стратегия обработки ошибок выхода за границы массива;

    снято требование, чтобы элементы массива принимали значения в заданном диапазоне.
    Ход работы
    Задание1. Определить операции инкремента для класса SafeArray using System; namespace ConsoleApplication1
    { class SafeArray
    { public SafeArray( int size) // конструктор
    { a = new int[size]; length = size;
    } public SafeArray( params int[ ] arr) // новый конструктор
    { length = arr.length; a = new int[length]; for( int i=0; i} public static SafeArray operator++ ( SafeArray x ) // операция ++
    {
    SafeArray temp = new SafeArray( x.length ); for( int i = 0; i < x.length; ++i) temp[ i ] = ++x.a[ i ]; return temp;
    } public int this[ int i ] // индексатор
    { get
    { if ( i >= 0 && i < length ) return a[i]; else throw new indexOutOfRangeException(); // исключение
    } set
    { if ( i >= 0 && i < length ) a[i] = value; else throw new IndexOutOfRangeException(); // исключение
    }
    } public void Print( string name ) // вывод на экран
    {
    Console.WriteLine( name + ":" ); for ( int i = 0; i < length; ++i )
    Console.Write( "\t" + a[i] );
    Console.WriteLine();
    } int[] a; // закрытый массив int length; // закрытая размерность .
    } class Class1
    { static void Main()
    { try
    {

    60
    SafeArray a1 = new SafeArray( 5, 2, -1, 1, -2 ); a1.Print( "Массив 1" ); a1++; a1.Print( "Инкремент массива 1" );
    } catch ( Exception e ) // обработка исключения
    {
    Console.WriteLine( e.Message );
    }
    }
    }
    }
    Бинарные операции
    Можно определять в классе следующие бинарные операции:
    + - * / % & | ^ << >> == != > < >= <=
    Синтаксис объявителя бинарной операции: тип operator бинарная_операция (параметр1, параметр2)
    Примеры заголовков бинарных операций: public static MyObject operator + ( MyObject m1, MyObject m2 ) public static bool operator == ( MyObject m1, MyObject m2 )
    Хотя бы один параметр, передаваемый в операцию, должен иметь тип класса, для которого она определяется. Операция может возвращать величину любого типа.
    Операции ==и!=,>и<,>=и<= определяются только парами и обычно возвращают логическое значение. Чаще всего в классе определяют операции сравнения на равенство и неравенство для того, чтобы обеспечить сравнение объектов, а не их ссылок, как определено по умолчанию для ссылочных типов. Перегрузка операций отношения требует знания интерфейсов, поэтому она рассматривается позжe.
    Пример определения операции сложения для класса SafeArray, описанного в предыдущем разделе, приведен в листинге 1.20. В зависимости от операндов операция либо выполняет поэлементное сложение двух массивов, либо прибавляет значение операнда к каждому элементу массива.
    Задание 2. Определение операции сложения для класса SafeArray using System; namespace ConsoleApplication1
    { class SafeArray
    { public SafeArray( int size )
    { a = new int [ size ]; length = size;
    } public SafeArray( params int [ ] arr )
    { length = arr.Length: a = new int [ length ]; for ( int i = 0; i < length; ++i ) a[ i ] = arr [ i ];
    } public static SafeArray operator + ( SafeArray x, SafeArray у ) // +
    { int len = x.length < y.length ? x.length : y.length;
    SafeArray temp = new SafeArray ( len ); for ( int i = 0; i < len; ++i ) temp[i] = x[i] + y[i]; return temp;
    } public static SafeArray operator + ( SafeArray x, int у ) // +

    61
    {
    SafeArray temp = new SafeArray ( x.length ); for ( int i = 0; i < x.length; ++i ) temp[i] = x[i] + y; return temp;
    } public static SafeArray operator + ( int x, SafeArray у )
    { // +
    SafeArray temp = new SafeArray(y.length); for ( int i = 0; i < y.length; ++i ) temp[i] = x + y[i]; return temp;
    } public static SafeArray operator ++ ( SafeArray x ) // ++
    {
    SafeArray temp = new SafeArray(x.length); for ( int i = 0; i < x.length; ++i ) temp[i] = ++x.a[i]; return temp;
    } public int this[int i]
    { // [ ] get
    { if ( i >= 0 && i < length ) return a[i]; else throw new IndexOutOfRangeException();
    } set
    { if ( i >= 0 && i < length ) a[i] = value; else throw new IndexOutOfRangeException();
    }
    } public void Print( string name )
    {
    Console.WriteLine( name + ":" ); for ( int i = 0; i < length; ++i )
    Console.Write( "\t" + a [ I ] );
    Console.WriteLine();
    } int[] a; int length;
    } class Class1
    { static void Main()
    { try
    {
    SafeArray a1 = new SafeArray( 5, 2, -1, 1, -2 ); a1.Print( "Массив 1" );
    SafeArray a2 - new SafeArrayC 1. 0, 3 ); a2.Print( "Массив 2" ); a1++;
    SafeArray a3 = a1 + a2; a3.Print( "Сумма массивов 1 и 2" ); a1 = a1 + 100; // 1 a1.Print( "Массив 1 + 100" ); a1 = 100 + a1; // 2 a1.PrintC "100 + массив 1" );

    62 a2 += ++a2 +1; // 3 оторвать руки! a2.Print( "++a2, a2 + a2 + 1" );
    } catch ( Exception e )
    {
    Console.WriteLine( e.Message );
    }
    }
    }
    }
    Результат работы программы:
    Массив 1:
    5 2 -1 1 -2
    Массив 2:
    1 0 3
    Сумма массивов 1 и 2:
    7 3 3
    Массив 1+100:
    106 103 100 102 99 100 + массив 1:
    206 203 200 202 199
    ++a2, a2 +a2 + 1:
    5 3 9
    Обратите внимание: чтобы обеспечить возможность сложения с константой, операция сложения перегружена два раза для случаев, когда константа является первым и вторым операндом (операторы 2 и 1).
    Сложную операцию присваивания += (оператор 3) определять не требуется, да это и невозможно. При ее выполнении автоматически вызываются сначала операция сложения, а потом присваивания. В целом же оператор 3 демонстрирует недопустимую манеру программирования, поскольку результат его выполнения неочевиден.
    ПРИМЕЧАНИЕ
    В перегруженных методах для объектов применяется индексатор. Для повышения эффективности можно обратиться к закрытому полю-массиву и непосредственно, например: temp.a[i] = х + y.a[i].
    Операции преобразования типа
    Операции преобразования типаобеспечивают возможность явного и неявного преобразования между пользовательскими типами данных. Синтаксис объявителя операции преобразования типа: implicit operator тип ( параметр ) // неявное преобразование explicit operator тип ( параметр ) // явное преобразование
    Эти операции выполняют преобразование из типа параметра в тип, указанный в заголовке операции. Одним из этих типов должен быть класс, для которого определяется операция. Таким образом, операции выполняют преобразование либо типа класса к другому типу, либо наоборот.
    Преобразуемые типы не должны быть связаны отношениями наследования. Примеры операций преобразования типа для класса Monster, описанного в разделе 6: public static implicit operator int( Monster m )
    { return m.health;
    } public static explicit operator Monster( int h )
    { return new Monster( h, 100, "Fromlnt" );
    }
    Ниже приведены примеры использования этих преобразований в программе. Не надо искать в них смысл, они просто иллюстрируют синтаксис:
    Monster Masha = new Monster( 200, 200, "Masha" );

    63
    Int i = Masha: // неявное преобразование
    Masha = (Monster) 500; // явное преобразование
    Неявное преобразованиевыполняется автоматически:

    при присваивании объекта переменной целевого типа, как в примере;

    при использовании объекта в выражении, содержащем переменные целевого типа;

    при передаче объекта в метод на место параметра целевого типа;

    при явном приведении типа.
    +Явное преобразование выполняется при использовании операции приведения типа.
    Все операции класса должны иметь разные сигнатуры. В отличие от других видов методов, для операций преобразования тип возвращаемого значения включается в сигнатуру, иначе нельзя было бы определять варианты преобразования данного типа в несколько других.
    Ключевые слова implicit иexplicitв сигнатуру не включаются, следовательно, для одного и того же преобразования нельзя определить одновременно явную и неявную версии.
    Неявное преобразованиеследует определять так, чтобы при его выполнении не возникала потеря точности и не генерировались исключения. Если эти ситуации возможны, преобразование следует описать как явное.
    1   2   3   4   5   6   7   8   9   10   ...   24


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