Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
С# ЛР 3.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
194.05 Кб
Скачать

Лабораторная работа №11

Тема: Структури. Класи. Інтерфейси

Мета роботи: навчитися створювати типи даних структури та перерахування, вивчити методи роботи зі структурами та перерахуваннями в програмі на С #, ознайомитися зі структурою класу, його створенням і використанням, описом членів-даних класу і різних методів доступу до них, можливістю створення і ініціалізації об'єктів класу за допомогою різних конструкторів.

Теоретичні відомості

Перечисление - это частный случай класса. Перечисление задает конечное множество возможных значений, которые могут получать объекты класса перечисление. Поскольку у перечислений нет собственных методов, то синтаксис объявления этого класса упрощается - остается заголовок и тело класса, содержащее список возможных значений:

[атрибуты][модификаторы]enum имя_перечисления[: базовый класс]

{список_возможных_значений}

Особенности объявления перечислений:

  • как и другие классы, перечисления могут быть объявлены непосредственно в пространстве имен проекта или могут быть вложены в описание класса. Последний вариант часто применяется, когда перечисление используется в одном классе и имеет атрибут доступа private;

  • константы разных перечислений могут совпадать. Имя константы всегда уточняется именем перечисления;

  • константы могут задаваться словами русского языка;

  • разрешается задавать базовый класс перечисления.

  • разрешается задавать не только базовый класс, но и указывать начальный элемент подмножества, на которое проецируется множество значений перечисления.

Часто бывает удобным создать набор значимых имен, которые будут представлять числовые значения. Представим себе, что вы создаете систему расчета заработной платы для сотрудников. Скорее всего, вам покажется более удобным вместо значений {0, 1, 2, 3} использовать понятные имена VP, Manager, Grunt и Contractor. Создание перечисле­ния для наших целей может выглядеть так:

Значения по умолчанию:

еnиm ЕmрТуре {

Manager, // = 0

Grunt, // = 1

Contractor, // = 2

VP // = 3

}

При необходимости можно задать значения:

enum EmpType {

Manager = 102,

Grunt, // = 103

Contractor, // = 104

VP // = 105

}

Для элементов перечисления вовсе не обязательно использовать строго после­довательные числовые значения.

class EnumClass {

public static void AskForBonus(EmpType e) {

switch(e) {

case EmpType.Contractor:

Console.WriteLine(“You are already get enough cash..."); break;

case EmpType.Grunt:

Console.WriteLine("You havve got to be kidding..."); break;

case EmpType.Manager:

Console.WriteLine(“How about stock options instead?"); break;

case'EmpType.VP:

Console.WriteLine(“VERY GOOD. Sir!"); break;

default: break;

} }

public static int Main(string[] args) {

EmpType fred;

fred = EmpType.Contractor;

AskForBonus(fred);

return 0;

}}

Структуры С# можно рассматривать как особую разновидность классов. С классами структуры роднит многое: для структур можно определять конструк­торы (только с параметрами), структуры могут реализовывать интер­фейсы. Синтаксис объявления структуры аналогичен синтаксису объявления класса:

[Атрибуты][модификаторы]struct имя_структуры [:список_интерфейсов] {тело_структуры}

//Программа 1. Использование перечислений и структур в программах на C#

enum EmpType : byte {

Manager = 10,

Grunt = 1,

Contractor = 100,

VP = 9

}

struct Employee {

public EmpType title; // Одно из полей структуры – перечисление

public string name;

public short deptID:

}

class StructTester {

public static int Main(string[] args) {

Employee fred;

fred.deptID = 40;

fred.name = "Fred";

fred.title = EmpType.Grunt;

return 0;

}}

Для структур можно определить конструкторы, но все созданные вами конструкторы должны принимать параметры:

struct Employee {

public EmpType title;

public string name;

public short deptID;

// Конструктор

public Employee (EmpType et, string n, short d) {

title = et;

name = n;

deptID = d;

}}

При помощи такого определения структуры, в котором предусмотрен конструктор, можно создавать новых сотрудников следующим образом:

class StructTester {

public static int Main(string[] args) {

Employee maгу =new Employee (EmpType.VP, "Mary", 10);

return 0;

}}

Конечно же, структуры могут быть использованы в качестве принимаемых и возвращаемых методами параметров. Например, пусть в нашем классе StructTester будет предусмотрен метод DisplayEmpStats():

public void DisplayEmpStats (Employee e) {

Console.WriteLine(“Here is {0}\'s info:", e.name);

Console.WriteLine("Department ID: {0}", e.deptID);

Console.WriteLine(“Title: {0}", Enum.Format(typeof(EmpType), e.title, "G"));

}

Так можно выполнить программу с использованием DisplayEmpStats(). Выведем данные о Мэри и Фреде:

public static int Main(string[] args) {

StructTester t = new StructTester();

t.DisplayEmpStats(mary);

t.DisplayEmpStats(fred);

return 0;

}

Упаковка и распаковка — это наиболее удоб­ный способ преобразования структурного типа в ссылочный, и наоборот. Основное назначение структур — возможность получения некоторых преимуществ объектной ориентации, но при более высокой производительности за счет размещения в стеке. Чтобы преобразовать структуру в ссылку на объект, необходимо упако­вать ее экземпляр:

Employee stan = new Employee (EmpType.Grunt, "Stan", 10);

object stanlnBox = stan;

// можно распаковать и производить операции с содержимым

public void UnboxThisEmployee(object о) {

Employee temp = (Employee)o;

Console.WriteLine(temp.name + "is alive!");

}

Классы в c# [атрибуты][модификаторы]class имя_класса [:список_родителей] {тело_класса}

Возможными модификаторами в объявлении класса могут быть модификаторы new, abstract, sealed, которые связаны с наследованием, и четыре модификатора доступа, два из которых - private и protected - могут быть заданы только для вложенных классов. Обычно класс имеет атрибут доступа public, являющийся значением по умолчанию. Так что в простых случаях объявление класса выглядит так:

public class Employee {тело_класса}

В теле класса могут быть объявлены:

  • константы;

  • поля;

  • конструкторы и деструкторы;

  • методы;

  • события;

  • делегаты;

  • вложенные классы (структуры, интерфейсы, перечисления).

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

Члены классов С# и бывают следующих видов:

  • Поле. Так называется член-переменная, содержащий некоторое значение. В ООП поля иногда называют данными объекта. К полю можно применять несколько модификаторов в зависимости от того, как вы собираетесь его использовать. В число модификаторов входят static, readonly и const.

  • Метод. Это реальный код, воздействующий на данные объекта (или поля).

  • Свойства. Их иногда называют «разумными» полями (smart fields), поскольку они на самом деле являются методами, которые клиенты класса воспринимают как поля. Это обеспечивает клиентам большую степень абстрагирования за счет того, что им не нужно знать, обращаются ли они к полю напрямую или через вызов метода-аксессора.

  • Константы. Как можно предположить, исходя из имени, константа — это поле, значение которого изменить нельзя.

  • Индексаторы. Если свойства — это «разумные» поля, то индексаторы —это «разумные» массивы, так как они позволяют индексировать объекты методами-аксессорами get и set. С помощью индексатора легко проиндексировать объект для установки или получения значений.

  • События. Событие вызывает исполнение некоторого фрагмента кода. События — неотъемлемая часть программирования для Microsoft Windows. Например, события возникают при движении мыши, щелчке или изменении размеров окна.

class Employee {

// Внутренние закрытые данные класса

private string fullName;

private int empID;

private float currPay;

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

public Employee() {}

public Employee(string fullName, int empID, float currPay) {

this. fullName = fullName;

this.empID = empID;

this. currPay = currPay;

}

// Метод для увеличения зарплаты сотрудника

public void GiveBonus(float amount)

{ currPay += amount; }

// Метод для вывода сведений о текущем состоянии объекта

public virtual void DisplayStats() {

Console. WriteLine("Name: {0}", fullName):

Console.WriteLine(“Pay: {0}", currPay):

Console.WriteLine(“ID: {0}", empID);

}

}

public static void Main() {

Employee e = new Employee(“Joe", 80, 30000);

e.GiveBonus(200):

Employee e2:

e2 = new Employee("Beth", 81, 50000);

e2.GiveBonus(1000);

e2.DisplayStats():

}

Таблица 2.1 – Модификаторы доступа к членам классов

Модификатор доступа

Описание

public

Член доступен вне определения класса и иерархии производных классов.

protected

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

private

Член недоступен за пределами области видимости определяющего его класса. Поэтому доступа к этим членам нет даже у производных классов.

internal

Член видим только в пределах текущей единицы компиляции. Модификатор доступа internal в плане ограничения доступа является гибридом public и protected, зависимым от местоположения кода.

Методы-свойства

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

  • чтение, запись (Read, Write);

  • чтение, запись при первом обращении (Read, Write-once);

  • только чтение (Read-only);

  • только запись (Write-only);

  • ни чтения, ни записи (Not Read, Not Write).

Открытость свойств (атрибут public) позволяет реализовать только первую стратегию. В языке C# принято, как и в других объектных языках, свойства объявлять закрытыми, а нужную стратегию доступа организовывать через методы. Для эффективности этого процесса и введены специальные методы-свойства.

Рассмотрим класс Person, у которого пять полей: fam, status, salary, age, health, характеризующих соответственно фамилию, статус, зарплату, возраст и здоровье персоны. Для каждого из этих полей может быть разумной своя стратегия доступа. Возраст доступен для чтения и записи, фамилию можно задать только один раз, статус можно только читать, зарплата недоступна для чтения, а здоровье закрыто для доступа и только специальные методы класса могут сообщать некоторую информацию о здоровье персоны:

// Программа 2. Свойства в класса на C#

public class Person {

//поля (все закрыты)

string fam="", status="", health="";

int age=0, salary=0;

//стратегия: Read,Write-once

public string Fam {

set {if (fam == "") fam = value;}

get {return(fam);}

}

//стратегия: Read-only

public string Status {

get {return(status);}

}

//стратегия: Read,Write

public int Age {

set {

age = value;

if(age < 7) status ="ребенок";

else if(age <17) status ="школьник";

else if (age < 22) status = "студент";

else status = "служащий";

}

get {return(age);}

}

//стратегия: Write-only

public int Salary {

set {salary = value;}

}

}

public void TestPersonProps(){

Person pers1 = new Person();

pers1.Fam = "Петров";

pers1.Age = 21;

pers1.Salary = 1000;

Console.WriteLine ("Фам={0}, возраст={1}, статус={2}", pers1.Fam, pers1.Age, pers1.Status);

pers1.Fam = "Иванов"; pers1.Age += 1;

Console.WriteLine ("Фам={0}, возраст={1}, статус={2}", pers1.Fam, pers1.Age, pers1.Status);

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]