• Добро пожаловать на сайт - Forumteam.digital !

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

    Группа в телеграме (подпишитесь, что бы не потерять нас) - ForumTeam Chat [Подписатся]
    Связь с администратором - @ftmadmin

14. Изучаем классы.

Redman

<FORUMTEAM>
Команда форума
Регистрация
13.11.17
Сообщения
13.340
Реакции
8.377
Баллы
1.200
FTC
208¢
Классы.

И снова классы... Что же отличает классы C# от классов C++?

Уровни доступа

В языке C# доступ регулируется несколькими способами:

Доступ для членов класса:
87c5d278dd62.jpg


Доступом по умолчанию является 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]);
    }
}
 
Сверху Снизу