Введение в C#: классы
Информация - Компьютеры, программирование
Другие материалы по предмету Компьютеры, программирование
double width, double height)
{
this.width = width;
this.height = height;
}
public double Square()
{
return (width * height);
}
}
class CCircle: CShape, IShape
{
double radius;
public CCircle(double radius)
{
this.radius = radius;
}
public double Square()
{
return (Math.PI * radius * radius);
}
}
class Example_3
{
public static void Main()
{
CRectangle rect = new CRectangle(3, 4);
CCircle circ = new CCircle(5);
Console.WriteLine(rect.Square());
Console.WriteLine(circ.Square());
}
}
Оба объекта, rect и circ, являются производными от базового класса CShape и тем самым они наследуют единственный метод IsShape(). Задав имя интерфейса IShape в объявлениях CRectangle и CCircle, мы указываем на то, что в данных классах содержится реализация всех методов интерфейса IShape. Кроме того, члены интерфейсов не имеют модификаторов доступа. Их область видимости определяется непосредственно реализующим классом.
Свойства
Рассматривая классы языка C#, просто нельзя обойти такое новшество, как свойства (properties). Надо сказать, что здесь чувствуется влияние языков Object Pascal и Java, в которых свойства всегда являлись неотъемлемой частью классов. Что же представляют собой эти самые свойства? С точки зрения пользователя, свойства выглядят практически так же, как и обычные поля класса. Им можно присваивать некоторые значения и получать их обратно. В то же время свойства имеют бо,льшую функциональность, так как чтение и изменение их значений выполняется с помощью специальных методов класса. Такой подход позволяет изолировать пользовательскую модель класса от ее реализации. Поясним данное определение на конкретном примере:
using System;
using System.Runtime.InteropServices;
class Screen
{
[DllImport(”kernel32.dll”)]
static extern bool SetConsoleTextAttribute(
int hConsoleOutput, ushort wAttributes
);
[DllImport(”kernel32.dll”)]
static extern int GetStdHandle(
uint nStdHandle
);
const uint STD_OUTPUT_HANDLE = 0x0FFFFFFF5;
static Screen()
{
output_handle = GetStdHandle(STD_OUTPUT_HANDLE);
m_attributes = 7;
}
public static void PrintString(string str)
{
Console.Write(str);
}
public static ushort Attributes
{
get
{
return m_attributes;
}
set
{
m_attributes = value;
SetConsoleTextAttribute(output_handle, value);
}
}
private static ushort m_attributes;
private static int output_handle;
}
class Example_4
{
public static void Main()
{
for (ushort i = 1; i < 8; i++)
{
Screen.Attributes = i;
Screen.PrintString(”Property Demo
”);
}
}
}
Программа выводит сообщение Property Demo, используя различные цвета символов (от темно-синего до белого). Давайте попробуем разобраться в том, как она работает. Итак, сначала мы импортируем важные для нас функции API-интерфейса Windows: SetConsoleTextAttribute и GetStdHandle. К сожалению, стандартный класс среды .NET под названием Console не имеет средств управления цветом вывода текстовой информации. Надо полагать, что корпорация Microsoft в будущем все-таки решит эту проблему. Пока же для этих целей придется воспользоваться службой вызова платформы PInvoke (обратите внимание на использование атрибута DllImport). Далее, в конструкторе класса Screen мы получаем стандартный дескриптор потока вывода консольного приложения и помещаем его значение в закрытую переменную output_handle для дальнейшего использования функцией SetConsoleTextAttribute. Кроме этого, мы присваиваем другой переменной m_attributes начальное значение атрибутов экрана (7 соответствует белому цвету символов на черном фоне). Заметим, что в реальных условиях стоило бы получить текущие атрибуты экрана с помощью функции GetConsoleScreenBufferInfo из набора API-интерфейса Windows. В нашем же случае это несколько усложнило бы пример и отвлекло от основной темы.
В классе Screen мы объявили свойство Attributes, для которого определили функцию чтения (getter) и функцию записи (setter). Функция чтения не выполняет каких-либо специфических действий и просто возвращает значение поля m_attributes (в реальной программе она должна бы возвращать значение атрибутов, полученное с помощью все той же GetConsoleScreenBufferInfo). Функция записи несколько сложнее, так как кроме тривиального обновления значения m_attributes она вызывает функцию SetConsoleTextAttribute, устанавливая заданные атрибуты функций вывода текста. Значение устанавливаемых атрибутов передается специальной переменной value. Обратите внимание на то, что поле m_attributes является закрытым, а стало быть, оно не может быть доступно вне класса Screen. Единственным способом чтения и/или изменения этого метода является свойство Attributes.
Свойства позволяют не только возвращать и изменять значение внутренней переменной класса, но и выполнять дополнительные функции. Так, они позволяют произвести проверку значения или выполнить иные действия, как показано в вышеприведенном примере.
В языке C# свойства реализованы на уровне синтаксиса. Более того, рекомендуется вообще не использовать открытых полей классов. На первый взгляд, при таком подходе теряется эффективность из-за того, что операции присваивания будут заменены вызовами функций getter и setter. Отнюдь! Среда .NET сгенерирует для них соответствующий inline-код.
Делегаты
Язык программирования C# хотя и допускает, но все же не поощряет использование указателей. В некоторых ситуациях бывает особенно трудно обойтись без указателей на функции. Для этих целей в C# реализованы так называемые делегаты (delegates), которые иногда еще называют безопасными аналогами указателей на функцию. Ниже приведен простейший пример использования метода-делегата:
using System;
delegate void MyDelegate();
class Example_5
{
static void Func()
{
System.Console.WriteLine(MyDelegate.Func());
}
public static void Main()
{
MyDelegate f = new MyDelegate(Func);
f();
}
}
Помимо того что делегаты обеспечивают типовую защищенность, а следовательно, и повышают безопасность кода, они отл?/p>