Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Лабораторная работа № 12
Цель работы изучить работу с классами, получить практические навыки в составлении программ.
2 Общие сведения
Для чего нужны классы. Представьте себе, что у вас есть некоторый объект, который характеризуется рядом свойств. Например, работник на некой фирме. У него есть такие свойства, как фамилия, возраст, стаж и т. п. Так вот, в этом случае удобно каждого работника описывать не рядом независимых переменных (строкового типа для фамилии, целого типа для возраста и стажа), а одной переменной типа Worker, внутри которой и содержатся переменные для фамилии, возраста и стажа. Здесь самое важное то, что в переменной типа Worker содержатся другие переменные. Конечно, типа Worker среди встроенных типов данных нет, но это не беда мы можем ввести его.
Еще одна важная вещь: в классах помимо переменных разных типов содержатся функции (или, что то же самое, методы) для работы с этими переменными. Скажем, в нашем примере с классом Worker логично ввести специальные функции для записи возраста и стажа. Функции будут, в частности, проверять правильность вводимой информации. Например, ясно, что возраст у работника не может быть отрицательным или большим 150. Так вот, наша функция и будет проверять правильность введенного пользователем возраста.
Давайте рассмотрим первый пример класса. Создайте новое консольное приложение для С# и введите следующий текст:
using System;
namespace test
{
//Начало класса
class Worker
{
public int age = 0;
public string name;
}
//Конец класса
class Test
{
[STAThread]
static void Main(string[] args)
{
Worker wrkl = new Worker();
wrkl.age = 30;
wrkl.name = "Петров Иван Сергеевич";
Console.WriteLine(wrkl.name + " - " + wrkl.age + " года");
}
}
}
Запустите программу. Она, как и следовало ожидать, выведет на экран
"Петров Иван Сергеевич - 30". Разберем этот код.
class Worker
{
public int age = 0;
public string name;
}
Определяем класс Worker. Внутри этого класса существуют две переменные целая age для возраста и name строкового типа для имени.
Обратите внимание, что, в отличие от C/C++, мы можем задавать некоторое начальное значение непосредственно сразу после объявления переменной:
public int age=0;
Начальное значение задавать вовсе не обязательно это видно по переменной name. Перед переменными мы пишем ключевое слово public. Это означает, что переменная (или функция) будет видна вне класса. Если мы не напишем перед переменной никакого модификатора доступа, или укажем private, то переменная не будет видна снаружи класса, и ее смогут использовать только функции этого же класса (т. е. она будет для «внутреннего использования»). Далее в строчке:
Worker wrkl = new Worker();
заводим экземпляр класса в куче (heap) и возвращаем на него ссылку. Затем в строчках:
wrkl.age = 30;
wrkl.name = "Петров Иван Сергеевич";
Console.WriteLine(wrkl.name + " - " + wrkl.age + " года");
используем наш класс, присваивая некоторые значения для возраста и имени и выводя их потом на экран.
2.1 Создание классов
2.1.1 Объявление класса
В языке С# определение класса не обязательно должно иметь методы конструктор и деструктор.
Управляемый код на языке С# избавлен от необходимости освобождения памяти, выделяемой под объекты, так как это реализуется средой NET Framework. Поэтому основное назначение деструктора в языке C# - это освобождение неуправляемых ресурсов, таких как окна, файлы, сетевые соединения и т.п.
Язык C# поддерживает три типа конструкторов:
Конструктор экземпляра объекта имеет следующее формальное описание:
[атрибуты] [модификаторы_доступа]
имя_конструктора([список_формальных_параметров])
[:base (список_аргументов) | :this (список_аргументов)]
{ тело_конструктора }
Ключевое слово base определяет явный вызов конструктора базового класса, а ключевое слово this - вызов конструктора данного класса с указанным списком параметров.
Например:
public class AClass1
{
public AClass1()// Объявление конструктора
{
}
}
Ключевое слово class определяет имя объявляемого класса. Тело объявляемого класса указывается в фигурных скобках.
Ключевое слово public - это модификатор доступа, указывающий, что объявляемые после него идентификаторы (имена классов или методов) будут общедоступны (модификатор доступа позволяет определить область видимости переменных и методов - членов класса).
По умолчанию все переменные и методы - члены класса, заданные без модификатора доступа, считаются private-переменными (называемыми иногда приватными или закрытыми). Приватные переменные доступны только внутри экземпляра класса и не могут быть использованы во внешних функциях модуля.
2.1.2 Модификаторы доступа
В языке C# применяются следующие модификаторы доступа:
Для любого члена класса или объектного типа разрешено указывать только один модификатор доступа, за исключением комбинации protected internal, регламентирующей ограничение доступа наследуемыми классами текущего проекта.
Например:
class A
{
protected int x = 100;
}
class B : A
{
void M1()
{
A a1 = new A(); // Создание объекта типа A
B b1 = new B(); // Создание объекта типа B
// a1.x = 200; - доступ не разрешен
b1.x = 200; // Правильно реализованный доступ
}
}
Отметим, что пространство имен не может иметь модификатора доступа. Язык C# поддерживает использование вложенных классов.
Типы верхнего уровня, которые не являются вложенными в другие типы, могут иметь модификатор доступа только internal (по умолчанию) или public. Если модификатор доступа не указан, то применяется доступ по умолчанию. В следующей таблице отображены модификаторы доступа для вложенных типов, являющихся членами других типов.
Таблица 1
Член, определяемый в: |
Модификатор доступа, используемый по умолчанию |
Допустимые модификаторы доступа, используемые для членов |
enum |
Public |
- |
class |
private |
public protected internal private protected internal |
interface |
public |
- |
struct |
private |
public internal private Структуры не могут иметь модификатор доступа protected,так как не могут быть наследуемы |
Например:
using System;
namespace MyNameSpace
{
public class A
{
public static int myPublicInt;
internal static int myInternalInt;
private static int myPrivateInt = 0;
public class Nest1 // "Вложенный" член класса
{
public static int myPublicInt;
internal static int myInternalInt;
private static int myPrivateInt = 0;
}
private class Nest2 // "Вложенный" член класса
{
public static int myPublicInt = 0;
internal static int myInternalInt = 0;
private static int myPrivateInt = 0;
}
}
public class MyClass
{
public static int Main()
{
// Доступ к членам класса A:
A.myPublicInt = 1; // Доступ не ограничен
A.myInternalInt = 2; // Только в текущем проекте
// A.myPrivateInt = 3; - ошибка: нет
// доступа вне класса
// Доступ к членам класса Nest1:
A.Nest1.myPublicInt = 1; // Доступ не ограничен
A.Nest1.myInternalInt = 2; // Только в текущем проекте
// A.Nest1.myPrivateInt = 3; - ошибка: нет
// доступа вне класса Nest1
// Доступ к членам класса Nest2:
// A.Nest2.myPublicInt = 1; - ошибка: нет
// доступа вне класса A
// A.Nest2.myInternalInt = 2; - ошибка: нет
// доступа вне класса A
// A.Nest2.myPrivateInt = 3; - ошибка: нет
// доступа вне класса Nest2
return 0;
}
}
}
2.1.3 Создание экземпляра класса
Для использования переменных или методов класса следует создать объект - экземпляр класса.
В языке C# экземпляр класса всегда создается при помощи оператора new. Если класс имеет несколько конструкторов, то при создании переменной указывается требуемый конструктор.
Место выделения памяти под объект зависит от типа создаваемого объекта: объекты ссылочных типов размещаются в куче, а объекты размерных типов - в стеке.
Объявление переменной объектного типа в языке С# не создает объекта, а только определяет идентификатор указанного типа. Обратите внимание, что во многих объектно-ориентированных языках, таких как С++, объявление переменной объектного типа также становится и созданием экземпляра данного типа.
Например:
using System;
namespace MyNS
{
public class A
{ public A() // Конструктор без параметров
{ Console.WriteLine("A()"); }
public A(int i) // Конструктор с одним параметром
{ Console.Write("A(i) i= ");
Console.WriteLine(i); }
}
}
using System;
namespace MyNS
{
class MyClass
{
static void Main(string[] args)
{ A acl1= new A(); // Создание экземпляра класса
A acl2= new A(987);
}
}
}
2.1.4 Явный вызов конструктора
Определение конструктора может содержать явный вызов конструктора того же класса. Вызываемый конструктор указывается после имени определяемого конструктора со списком параметров через символ двоеточия. Вызываемый конструктор может быть определен ключевым словом this - для вызова конструктора из того же самого класса, или ключевым словом base - для вызова конструктора базового класса. Явно вызываемый конструктор будет выполнен до выполнения конструктора, в котором он указывается.
Например:
public class A
{ public A():this(222) // Конструктор без параметров
{ }
public A(int i) // Конструктор с одним параметром
{ }
}
2.1.5 Методы члены класса
Среда проектирования Visual Studio .NET дает возможность использовать мастер создания метода - члена класса (в окне Class View выбрать имя класса и выполнить команду контекстного меню Add|Add Metod). Список Modifier. диалога. C# Metod Wizard позволяет указать один из следующих модификаторов параметра метода:
Например:
public void Metod1(int i, ref int j, out int k)
{ }
При обращении к методу или полю - членам класса используется операция . (точка) - доступ к члену класса. Имя поля или метода члена класса квалифицируется именем экземпляра класса.
Язык C# позволяет использовать методы с переменным числом параметров. Для метода с переменным числом параметров должны быть выполнены следующие правила:
Количество параметров в переменном списке параметров определяется свойством Length .
Например:
using System;
public class MyClass1
{
public static void UseParams1(params int[] list)
{
// Отображение списка параметров
for ( int i = 0 ; i < list.Length ; i++ )
Console.WriteLine(list[i]);
}
public static void UseParams2(params object[] list)
{ // В переменном списке параметров могут быть
// объекты различных типов
for ( int i = 0 ; i < list.Length ; i++ )
Console.WriteLine((object)list[i]);
}
public static void UseParams3(int k,params object[] list)
{ // В переменный список параметров
// включаются параметры, начиная
// со второго
for ( int i = 0 ; i < list.Length ; i++ )
Console.WriteLine((object)list[i]);
}
public static void Main()
{
UseParams1(1, 2, 3, 4, 5);
UseParams1(1, 2);
int[] myarray = new int[3] {1,2,3};
UseParams1(myarray);
UseParams2(111, 'f', "string");
UseParams3(111, 'f', "string");
}
}
2.1.6 Перегрузка (Overloading)
Часто бывает удобно иметь две функции, которые выполняют одну и ту же работу, но принимают разные параметры. Это особенно часто применимо по отношению к конструкторам, если существует несколько способов создания объекта класса.
class Point {
// создать новый point из x и y значений
public Point(int x, int y) {
this.x = x;
this.y = y;
}
// создание point из point
public Point(Point p) {
this.x = p.x;
this.y = p.y;
}
int x;
int y;
}
class Test {
public static void Main() {
Point myPoint = new Point(10, 15);
Point mySecondPoint = new Point(myPoint);
}
}
Здесь класс имеет два конструктора: один вызывается с двумя параметрами x и y, а второй принимает в качестве параметра ссылку на другой объект класса Point. В функции Main() используются оба конструктора.
При вызове перегруженной функции компилятор выбирает подходящую функцию путем сравнения параметров, используемых при вызове и при объявлении функции.
Для вариантов заданий к лабораторной работе № 10 создать полноценный класс, содержащий по возможности все его виды элементов: поля, конструкторы, свойства, методы и т.д.
4.1. Титульный лист.
4.2. Краткое теоретическое описание.
4.3. Задание на лабораторную работу, включающее математическую формулировку задачи.
4.4. Результаты выполнения работы, включающие схему алгоритма, тексты программ, результаты вычислений.
PAGE 171