Programming Taskbook


E-mail:

Пароль:

Регистрация пользователя   Восстановление пароля

 

ЮФУ SMBU

Электронный задачник по программированию

©  М. Э. Абрамян (Южный федеральный университет, Университет МГУ-ППИ в Шэньчжэне), 1998–2024

 

PT for OOP | Выполнение задания OOP1Creat1 | Решение на языке C#

PrevNext


Решение на языке C#

Теперь приведем решение задачи OOP1Creat1 на языке C#. Несмотря на то, что в нем, как и в решении для языка C++, потребуется реализовать систему классов в полном объеме, включая все абстрактные классы и методы, решение получится достаточно коротким, благодаря компактности конструкций самого языка и обширному набору функций из стандартной библиотеки платформы .NET.

Будем по-прежнему использовать среду Visual Studio Code (задания на языке C# можно также выполнять в средах Visual Studio и SharpDevelop).

Начнем с обсуждения заготовки, созданной для этого задания. Ниже приводится текст этой заготовки, за исключением начальных директив using для подключения пространств имен, а также директивы namespace определения пространства имен для класса MyTask:

public class MyTask : PT
{
    public abstract class Product
    {
        public abstract string GetInfo();
        public abstract void Transform();
    }

    // Implement the ConcreteProduct1
    //   and ConcreteProduct2 descendant classes

    public abstract class Creator
    {
        protected abstract Product FactoryMethod(string info);
        public string AnOperation(string info)
        {
            Product p = FactoryMethod(info);
            p.Transform();
            p.Transform();
            return p.GetInfo();
        }
    }

    // Implement the ConcreteCreator1
    //   and ConcreteCreator2 descendant classes;
    //   the AnOperation method should not be
    //   overridden in these classes

    public static void Solve()
    {
        Task("OOP1Creat1");

    }
}

В заготовках для языка C# все требуемые классы надо описывать в виде внутренних классов класса MyTask, который является потомком класса PT и содержит все элементы решения задачи. В частности, функция Solve тоже является методом класса MyTask. В остальном созданная заготовка очень похожа на заготовку для языка C++. Отметим лишь, что в языке C# все методы класса описываются непосредственно внутри описания класса и что после описаний классов не надо указывать точку с запятой. Некоторые отличия имеются также в правилах указания модификаторов доступа. Для языка C# модификатор override при переопределении виртуальных методов является обязательным, а в абстрактных методах вместо модификатора virtual используется модификатор abstract (а конструкция «= 0» не указывается).

Приведем вариант реализации конкретных классов-продуктов ConcreteProduct1 и ConcreteProduct2:

public class ConcreteProduct1 : Product
{
    string info;
    public override string GetInfo()
    {
        return info;
    }
    public ConcreteProduct1(string info)
    {
        this.info = info.ToLower();
    }
    public override void Transform()
    {
        StringBuilder s = new StringBuilder(info);
        for (int i = s.Length - 2; i >= 0; i--)
            if (s[i] != ' ')
                s.Insert(i + 1, " ");
        info = s.ToString();
    }
}

public class ConcreteProduct2 : Product
{
    string info;
    public override string GetInfo()
    {
        return info;
    }
    public ConcreteProduct2(string info)
    {
        this.info = info.ToUpper();
    }
    public override void Transform()
    {
        StringBuilder s = new StringBuilder(info);
        for (int i = s.Length - 2; i >= 0; i--)
            if (s[i] != '*')
                s.Insert(i + 1, "**");
        info = s.ToString();
    }
}

Для того чтобы обеспечить более эффективное преобразование поля info в методе Transform, мы используем класс StringBuilder, методы которого (в отличие от аналогичных методов класса string) преобразуют исходный объект StringBuilder, а не создают новые строковые объекты.

Реализация конкретных классов-создателей ConcreteCreator1 и ConcreteCreator2, как и для предыдущих языков, сложностей не представляет:

public class ConcreteCreator1 : Creator
{
    protected override Product FactoryMethod(string info)
    {
        return new ConcreteProduct1(info);
    }
}

public class ConcreteCreator2 : Creator
{
    protected override Product FactoryMethod(string info)
    {
        return new ConcreteProduct2(info);
    }
}

Организация ввода и вывода данных для языка C# похожа на вариант для языка Python, однако, чтобы обеспечить строгую типизацию, для ввода данных каждого типа необходимо использовать соответствующую функцию: GetInt(), GetDouble, GetString() и т. д. Вывод выполняется функцией Put с произвольным числом параметров. Используя эти средства ввода-вывода, получаем следующий вариант функции Solve:

public static void Solve()
{
    Task("OOP1Creat1");
    var c1 = new ConcreteCreator1();
    var c2 = new ConcreteCreator2();
    for (int i = 0; i < 5; i++)
    {
        string s = GetString();
        Put(c1.AnOperation(s), c2.AnOperation(s));
    }
}

От варианта для языка C++ данный фрагмент отличается также другим синтаксисом вызова конструктора, в котором используется ключевое слово new (как при создании в C++ объекта в динамической памяти). Такой синтаксис подчеркивает важную особенность объектной модели языка C#, в которой все классы являются ссылочными типами и их объекты всегда размещаются в динамической памяти.

Очень важным является то обстоятельство, что программист не должен заботиться об освобождении памяти, выделенной для хранения объектов, поскольку за это действие отвечает специальная подсистема платформы .NET — сборщик мусора (garbage collector, GC). Наличие сборщика мусора значительно упрощает разработку программ. Напомним, что в языке C++ тоже имеются средства для автоматического освобождения памяти — умные указатели, однако при их неправильном использовании в программе всё равно могут происходить утечки памяти. В языке C# и многих других современных языках (в том числе Python, Ruby и Java, которые рассматриваются в данном разделе), освобождение памяти выполняется полностью автоматически. Платой за подобную автоматизацию является некоторое (хотя и очень незначительное) замедление работы программы во время активизации сборщика мусора и выполнения им необходимых действий по освобождению памяти.

При описании объектов-создателей c1 и c2 мы использовали ключевое слово var, позволяющее не указывать тип описываемой переменной, если его можно вывести из инициализирующего выражения. Заметим, что это же слово var можно было использовать и при описании переменных i и s.

Запустив полученный вариант решения, мы увидим окно задачника с сообщением о том, что задание выполнено.


PrevNext

 

Рейтинг@Mail.ru

Разработка сайта:
М. Э. Абрамян, В. Н. Брагилевский

Последнее обновление:
01.01.2024