Главная · Карта сайта · Поиск · Статьи · Компьютерные курсы · Обучающие программы · Открытые проекты · Веб-программирование · Создание интернет-сайта · Полезные ссылки · Глоссарий · Контакты · Декабрь 09 2016 20:20:53
Последнее опубликованное

Что такое Model-View-Controller
Pattern Model-View-Controller

Как создать свой веб-сайт
Как создать свой сайт в интернете

Разное
Статистика

Классы, структуры, поля, свойства и методы


Создание классов
Наследование и полиморфизм
Переопределение не виртуального метода
Кратко о структурах


[Следующая страница]

1.1. Основы объектно-ориентированного подхода

Сначала была точка...

Выберем предметную область, объекты которой будем описывать средствами языка C#. Пусть это будет что-то из области геоинформационных систем (ГИС), тема которых близка автору этого материала. Начнем с малого и опишем класс ориентированной точечной геометрии, определяемой точкой и вектором (ориентацией геометрии) на плоскости. На данный момент нет желания углубляться в детали механизмов графического представления пространственных данных в ГИС, но стоит отметить, что с использованием точечной геометрии отображают объекты, размеры которых и протяженность на выбранном масштабе карты значения не имеют, а важно только их местоположение. Точечную геометрию могут отображать на картах ГИС не только в виде круглой точки, но и в виде произвольного символа, например, стрелки. Местоположение стрелки определяют координаты X и Y, а ее направление как раз и задается той самой ориентацией точечной геометрии. В ГИС обычно точки и векторы имеют три координаты, но здесь мы не будем усложнять картину мира и остановимся на двух. Поскольку понятие точки и вектора нам могут понадобиться не только для описания точечной геометрии, то имеет смысл их структуру определить в отдельных от ориентированной точечной геометрии классах. Примеры определения классов точки и вектора с подробными комментариями приведены ниже.

using System;
namespace CSharpQuickGuide
{
    //Класс 'Точка на плоскости'
    //Класс имеет модификатор доступа public, поэтому он доступен всем
    public class Point2D
    {
        //Поля (данные классы) обычно объявляют с модификатором private, делая их доступными
        //только для членом своего класса, а для изменения их значений определяют одноименные
        //свойства со своими модификаторами доступа.
        //Вещественное (double) поле m_X со значением по умолчанию = 0;
        private double m_X = 0;
        //Свойство X для изменения значения координаты 'X'
        public double X
        {
            //Раздел get можно убрать, и свойство 'X' будет только для записи
            get { return m_X; }
            //Раздел set можно убрать, и свойство 'X' будет только для чтения
            set { m_X = value; }
        }
        //Вещественное (double) поле m_Y со значением по умолчанию = 0;
        private double m_Y = 0;
        //Свойство Y для изменения значения координаты 'Y'
        public double Y
        {
            get { return m_Y; }
            set { m_Y = value; }
        }
        //Открытый (public) конструктор по умолчанию
        public Point2D() { }
        //Открытый (public) конструктор с параметрами - значениями координат
        public Point2D(double _X, double _Y)
            : this()
        {
            m_X = _X;
            m_Y = _Y;
        }
        //Защищенный (protected) конструктор можно вызывать только из конструкторов 
        //производных от Point2D классов: base(string)
        protected Point2D(string _Point) {/*разбор строки с координатами*/}
        //Копирование точки
        public void Copy(Point2D _Source) { _Copy(_Source); }
        //Метод _Copy имеет модификатор доступа internal и поэтому виден из всех классов
        //текущей сборки. Также, метод _Copy объявлен виртуальным (virtual), что позволяет
        //переопределить его реализацию в производных классах с помощью ключевого слова
        //override. Доступ к базовой реализации метода из производного класса по 
        //ключевому слову base, например, base._Copy(_Source)
        internal virtual void _Copy(Point2D _Source) { }
        //Копия текущего экземпляра класса
        public Point2D Clone()
        {
            Point2D _Clone = new Point2D();
            _Clone.Copy(this);

            return _Clone; 
        }
        //Статический (static) метод IsEqual можно вызывать, не создавая экземпляра класса,
        //используя имя типа: Point2D.Equals(p1, p2);
        public static bool IsEqual(Point2D _Point1, Point2D _Point2)
        {             
            return (_Point1.X == _Point2.X) && (_Point1.Y == _Point2.Y);     
        }
        //Проверка на равенство с текущим экземпляром класса
        public bool IsEqual(Point2D _Point) { return IsEqual(this, _Point); }
        //Переопределение (override) виртуальной функции ToString() базового класса
        //Object. Данная функция отвечает за представление экземпляра класса в виде
        //строки. По умолчанию выводит имя типа.
        public override string ToString()
        {
            return string.Format("{0};{1}", this.X, this.Y);
        }
    }
}

Класс Point2D имеет два конструктора: один без параметров или конструктор по умолчанию, и второй – конструктор с параметрами.

Конструктор - специальная процедура, которая запускается в момент создания нового экземпляра класса (объекта). Конструктор "конструирует" объект, инициализируя его поля конкретными значениями.
Определение конструктора с параметрами содержит вызов конструктора без параметров. Хотя здесь в этом смысла особого и нет, но на практике такая возможность крайне полезна, поскольку позволяет выделить общую часть инициализации класса в отдельном конструкторе. Точно также в любой конструктор можно поместить вызов любого другого конструктора (не только конструктора по умолчанию, которого может и не быть вовсе) с любым модификатором доступа: private, protected, internal и т.д.. Естественно, что в первую очередь выполняется код указанного после двоеточия конструктора, а потом уже код тела вызывающего конструктора.

Если вы хотите запретить создание ваших объектов посредством оператора new извне, то определите конструктор по умолчанию с модификатором private и создавайте экземпляры класса с помощью метода фабрики – любого статического метода вашего класса. Если вы хотите, чтобы конструктор по умолчанию был запрещен только пользователям вашего SDK

Software Development Kit (SDK) - набор программных компонентов, на основе которых создаются приложения.
, то сделайте его internal, protected или internal protected в зависимости от ваших целей. Модификатор internal может подойти для случая, когда экземпляры вашего класса создаются с помощью методов класса фабрики, определение которой находится в одной с вашим классом сборке (проекте). Такой прием следует применять, если требуется скрыть от внешнего мира некоторые элементы окружения вашей программы, которые вы используете для инициализации экземпляров класса, например: идентификатор активного соединения с базой данных. Модификатор protected подходит для случаев, когда конструктор играет вспомогательную роль: частично выполняет инициализацию класса - общую часть для всех производных классов, завершить которую в полном объеме может только экземпляр производного класса. Такой подход используют при определении абстрактных классов, которые будут рассмотрены в следующих разделах.

Модификаторы доступа
  • public: Доступ всем без исключений.
  • protected: Доступ в рамках содержащего класса и из классов – наследников (производных классов).
  • internal: Доступ всем в текущей сборке.
  • protected internal: Соответствует protected+internal, т.е. доступен всем в текущей сборке и производным классам других сборок.
  • private: Доступ только в рамках содержащего класса.
using System;
namespace CSharpQuickGuide
{
    //Класс 'Вектор на плоскости'
    public class Vector2D
    {
        //Вещественное (double) поле m_I;
        private double m_I;
        //Свойство I
        public double I
        {
            get { return m_I; }
            set { m_I = value; }
        }
        //Вещественное (double) поле m_J;
        private double m_J = 0;
        //Свойство J
        public double J
        {
            get { return m_J; }
            set { m_J = value; }
        }
        //Открытый (public) конструктор по умолчанию
        public Vector2D() { m_I = m_J = 0;}
        //Открытый (public) конструктор с параметрами - значениями координат
        public Vector2D(double _I, double _J)
            : this()
        {
            m_I = _I;
            m_J = _J;
        }
        //Данный конструктор разрешено использовать только в контексте сборки и
        //производными от Vector2D классами (internal protected)
        internal protected Vector2D(Point2D _PointFrom, Point2D _PointTo)
            : this()//Вызов конструктора по умолчанию
        {
            this.Evaluate(_PointFrom, _PointTo);   
        }
        //Определение вектора по двум точкам
        public void Evaluate(Point2D _PointFrom, Point2D _PointTo)
        {
            this.I = _PointTo.X - _PointFrom.X;
            this.J = _PointTo.Y - _PointFrom.Y;
        }
        //Свойство 'Длина вектора' только для чтения (раздел set отсутствует)
        public double Length
        {
            get
            {
                if (this.I == 0)
                    return System.Math.Abs(this.J);
            
                if (this.J == 0)
                    return System.Math.Abs(this.I);

                return System.Math.Sqrt(this.I * this.I + this.J * this.J);   
            }
        }
    }
}

Если у класса, поля, конструктора, метода или свойства модификатор доступа явно не определен, то по умолчанию он соответствует значению private.

Конструктор также может быть статическим (static), если вам необходимо инициализировать специальным образом статические члены вашего класса. Такие конструкторы еще называют конструкторами типа. Инициализация будет выполнена один раз в момент первого обращения к вашему типу при попытке создать его экземпляр или обратиться к статическому члену. Такие конструкции используют довольно редко, поскольку такое редко кому нужно (считать экземпляры определенного типа, например), да и инициализацию статических переменных советуют выполнять по месту их определения, а не в статическом конструкторе.

Конструкторы с большим числом параметров, если в этом нет крайней необходимости, также заводить не советую, поскольку, во-первых: все варианты не предусмотришь, а во-вторых: C# позволяет для инициализации свойств экземпляра использовать следующий компактный синтаксис:

Point2D Point = new Point2D() {X=10.2, Y=15.7};

Если вы хотите определить поля, значения которых не должны меняться, то у вас есть два способа это сделать: определить поле с модификатором const или с модификатором readonly. Разница в том, что первый вариант делает поле константой - требует его инициализации по месту определения и относит к статическим членам класса. Таким образом, обращение к константе не требует экземпляра класса, а выполняется через имя типа. Второй вариант делает поле константой на уровне экземпляра объекта - значение поля можно определить только в конструкторе и более нигде. Использование модификатора readonly может быть полезным при поиске ошибок, связанных с изменением значения полей, которые, по логике вашей программы, меняться и не должны.

Назначение модификаторов virtual и override в определении методов и функций класса Point2D будет приведено чуть позже при рассмотрении наследования типов.

Из определения класса Vector2D убраны некоторые, не столь важные на данный момент детали. Инициализация полей Vector2D в отличие от класса Point2D и только ради демонстрации этой самой разницы, осуществляется не по месту определения, а в теле конструктора по умолчанию.



[Следующая страница]

Компьютерные курсы и курсы программирования
Основы программирования

Курс для начинающих программистов на C# и VB.NET.

SQL 25™

Построение SQL запросов и работа с базой данных.

C# Quick Guide™

Программирование на C#. Краткое руководство.

RegEx

Применение регулярных выражений.

Plug-in архитектура

Примеры программной Plug-in архитектуры.

XML и его расширения

Язык разметки XML и его расширения с примерами.

HTML и разметка гипертекста

Языки HTML, XHTML и CSS с примерами разметки.

Основы веб-дизайна

Основы веб-дизайна: решения типовых задач верстки.

Программирование на PHP

Руководство по программированию на PHP для начинающих.

Справочные материалы

Шаблоны проектирования
Каталог шаблонов проектирования программных компонентов.

Рефакторинг кода
Каталог приемов рефакторинга программного кода.

Гость
Имя

Пароль



Забыли пароль?
Запросите новый здесь
.
Coding Craft. Все права защищены © 2011. Проект Инициативного Народного Фронта Образования - ИНФО-проект.