- Автор темы
- #1
Классы.
И снова классы... Что же отличает классы C# от классов C++?
Уровни доступа
В языке C# доступ регулируется несколькими способами:
Доступ для членов класса:
Доступом по умолчанию является private.
Доступ для классов верхнего уровня (классов, не вложенных в другие классы) ограничивается модификаторами internal и public (по умолчанию: internal).
Объявление полей и методов класса
В отличие от C++, модификатор доступа, должен появляться перед каждым отдельным полем или методом (иначе данный элемент будет иметь уровень доступа private).
Поля класса могут инициализироваться при объявлении
Поля класса могут иметь модификатор readonly, который означает, что значение данной переменной класса может либо быть задано сразу, либо в конструкторе (см. ниже), и в дальнейшем ее значение изменяться не может.
Объявление статических полей и методов класса
Для связи членов класса не с конкретными экземплярами класса, а с классом в целом, используются объявления статических переменных и статических функций.
Напоминаем, что статические переменные - это переменные, значения которых для каждого экземпляра класса одинаковы, а статические функции предназначены для работы со статическими переменными. Статическая функция, естественно, this не получает и поэтому обращаться к нестатическим членам класса не может. Для доступа к обычному члену класса необходимо создать объект класса, а для доступа к статическому элементу необходимо воспользоваться именем класса.
******
Так как в C# отсутствуют глобальные переменные и константы, то все объявления должны находиться внутри классов. В результате часто образуются классы, состоящие исключительно из статических членов. Необходимость в создании экземпляров у таких классов полностью отсутствует, ведь статические переменные вызываются через имя класса. Чтобы запретить создание экземпляров данного класса создают закрытый конструктор (см., например, класс System.Console).
******
Конструкторы
Идеология конструктов в C# мало чем отличается от конструкторов в языке C++. Конструктор - это функция, которая вызывается при создании объекта класса. Исключение составляет лишь статический конструктор - функция, которая вызывается перед созданием первого экземпляра класса (статическому конструктору ничего не известно о создаваемом объекте). Статический конструктор параметров не получает, а статических деструкторов не существует.
Деструкторы
В C# понятие деструктора отличается от изученного нами в C++. В C# деструктор (или завершитель) вызывается сборщиком мусора (см. подробности в следующих разделах) при освобождении объекта. Таким образом, мы не можем напрямую управлять вызовом деструктора, поэтому его ценность (в сравнении с деструктором C++) намного ниже. В C# нет возможности вызвать деструктор напрямую, он вызывается автоматически при сборке мусора.
Ссылочный тип
Объекты любых классов являются ссылочными типами. Это означает, что при объявлении они инициализируются null-значениями, и для них необходимо выделять память с помощью оператора new (естественно, объекты размещаются в куче).
И снова классы... Что же отличает классы C# от классов C++?
Уровни доступа
В языке C# доступ регулируется несколькими способами:
Доступ для членов класса:
Доступом по умолчанию является private.
Доступ для классов верхнего уровня (классов, не вложенных в другие классы) ограничивается модификаторами internal и public (по умолчанию: internal).
Объявление полей и методов класса
В отличие от C++, модификатор доступа, должен появляться перед каждым отдельным полем или методом (иначе данный элемент будет иметь уровень доступа private).
Код:
class SomeClass
{
public int i, j;
protected int k;
public void F()
{
}
}
Поля класса могут инициализироваться при объявлении
Код:
class SomeClass
{
public int i = 1, j = 2;
protected int k = 3;
public void F()
{
}
}
Поля класса могут иметь модификатор readonly, который означает, что значение данной переменной класса может либо быть задано сразу, либо в конструкторе (см. ниже), и в дальнейшем ее значение изменяться не может.
Код:
class SomeClass
{
public readonly int i = 7;
protected int k = 3;
public void F(int k)
{
// this - текущий экземпляр класса
this.k = k;
}
}
Объявление статических полей и методов класса
Для связи членов класса не с конкретными экземплярами класса, а с классом в целом, используются объявления статических переменных и статических функций.
Напоминаем, что статические переменные - это переменные, значения которых для каждого экземпляра класса одинаковы, а статические функции предназначены для работы со статическими переменными. Статическая функция, естественно, this не получает и поэтому обращаться к нестатическим членам класса не может. Для доступа к обычному члену класса необходимо создать объект класса, а для доступа к статическому элементу необходимо воспользоваться именем класса.
Код:
class SomeClass
{
// объявление константы подразумевает слово static !!!
// после объявления константа немодифицируема
const int Test = 1000;
public static int i = 100;
public static int GetI()
{
return i;
}
}
class Test
{
static void Main()
{
SomeClass s = new SomeClass();
Console.WriteLine(SomeClass.GetI());
SomeClass.i = 1000;
Console.WriteLine(SomeClass.GetI());
}
}
******
Так как в C# отсутствуют глобальные переменные и константы, то все объявления должны находиться внутри классов. В результате часто образуются классы, состоящие исключительно из статических членов. Необходимость в создании экземпляров у таких классов полностью отсутствует, ведь статические переменные вызываются через имя класса. Чтобы запретить создание экземпляров данного класса создают закрытый конструктор (см., например, класс System.Console).
******
Конструкторы
Идеология конструктов в C# мало чем отличается от конструкторов в языке C++. Конструктор - это функция, которая вызывается при создании объекта класса. Исключение составляет лишь статический конструктор - функция, которая вызывается перед созданием первого экземпляра класса (статическому конструктору ничего не известно о создаваемом объекте). Статический конструктор параметров не получает, а статических деструкторов не существует.
Код:
class SomeClass
{
// Если значение паременной зависит от конструктора,
// то производим инициализацию в нем,
// иначе присваиваем начальное значение сразу
static double d;
int i = 100;
string j;
static SomeClass()
{
d = 100.001;
}
public SomeClass()
{
j = "Hello";
}
public SomeClass(string value)
{
j = value;
}
public void Out()
{
Console.WriteLine(j);
Console.WriteLine(i);
Console.WriteLine(d);
}
}
class Test
{
static void Main()
{
SomeClass s1 = new SomeClass();
SomeClass s2 = new SomeClass("Test");
s1.Out();
s2.Out();
}
}
Деструкторы
В C# понятие деструктора отличается от изученного нами в C++. В C# деструктор (или завершитель) вызывается сборщиком мусора (см. подробности в следующих разделах) при освобождении объекта. Таким образом, мы не можем напрямую управлять вызовом деструктора, поэтому его ценность (в сравнении с деструктором C++) намного ниже. В C# нет возможности вызвать деструктор напрямую, он вызывается автоматически при сборке мусора.
Код:
class SomeClass
{
// Если значение паременной зависит от конструктора,
// то производим инициализацию в нем,
// иначе присваиваем начальное значение сразу
static double d;
int i = 100;
string j;
static SomeClass()
{
d = 100.001;
}
public SomeClass()
{
j = "Hello";
}
public SomeClass(string value)
{
j = value;
}
// Деструктор
~SomeClass()
{
Console.WriteLine("Деструктор");
}
public void Out()
{
Console.WriteLine(j);
Console.WriteLine(i);
Console.WriteLine(d);
}
}
class Test
{
static void Main()
{
SomeClass s1 = new SomeClass();
SomeClass s2 = new SomeClass("Test");
s1.Out();
s2.Out();
}
}
Ссылочный тип
Объекты любых классов являются ссылочными типами. Это означает, что при объявлении они инициализируются null-значениями, и для них необходимо выделять память с помощью оператора new (естественно, объекты размещаются в куче).
Код:
class Test
{
static void Main()
{
string [] m = new string[]{"4","5","3","9","1"};
string [] n = new string[3];
// память, выделенную под массив n, через какое-то время удалит
// сборщик мусора, а теперь n и m ссылаются на один и тот же
// участок памяти, что не всегда есть хорошо
n = m;
n[0] = "1000";
// выводимые данные одинаковы
Console.WriteLine(m[0]);
Console.WriteLine(n[0]);
}
}