Урок четвёртый: отладка кода (перевод)

Из этого урока вы узнаете как использовать отладчик Visual Studio для пошагового выполнения кода, чтобы следить за выполнением программы; а также отслеживать значения переменных по мере выполнения кода.
Редко с первого раза можно написать отлично работающую программу. Даже если вы не допустили ошибок, которые не позволят Visual Studio создать ваш плагин, вполне вероятно, что вы допустили ошибку в программной логике, которая заставляет выводить неожиданные результаты. Ошибки в вашем коде называются багами, а процесс анализа вашего кода, изучающий ход выполнения программы и значения переменных, называется отладкой (дебагинг).
Чтобы отладить код вашего плагин, вам придётся запустить AutoCAD из вашего отладчика Visual Studio и запустить ваш плагин в AutoCAD*.
* Если вы используете примеры готовых проектов, а не начинаете с нуля и шагов, описанных здесь, предполагается, что вы установили AutoCAD в папку C: \ Program Files \ Autodesk \ AutoCAD 20xx. Если место папки установки AutoCAD отличается, то для отладки завершённых примеров проектов вы должны выполнить следующие шаги.
Это легко сделать в профессиональных версиях Visual Studio – параметр My Project позволяет вам установить исполняемый файл для запуска при запуске отладчика:
Однако этот функционал не отображается через среду IDE Visual Studio. Именно поэтому вы создали свой проект в уроке 1 с помощью мастеров AutoCAD c помощью AutoCAD.NET Wizard, вместо того, чтобы создавать его используя библиотеки классов. Если вы установите правильное расположение AutoCAD в диалоговом окне конфигурации, этот параметр будет создан, даже если вы не можете изменить его через пользовательский интерфейс Visual Studio.
Если по какой-то причине Wizard не установил это корректно или вы решили использовать проект Class Library, вы можете вручную настроить AutoCAD 20xx на запуск отладчиком, выполнив следующие инструкции.
Запуск отладчика
Если вы закрыли Visual Basic .NET IDE, запустите её снова и откройте проект, который вы сохранили в уроке 1.
Чтобы начать процесс отладки, просто откройте меню Debug и выберите Start debugging или нажмите F5. Это запустит AutoCAD 20хх из вашего отладчика.

Вы должны запустить AutoCAD таким образом, чтобы ваш отладчик мог подключиться к процессу AutoCAD, чтобы отслеживать выполнение кода, который вы скомпилировали в свой подключаемый DLL.
Если во время этого у вас открыто окно Visual Studio Community Immediate, вы увидите много текста, пролистывающего это окно. Некоторые части этого текста выглядят страшно, так как содержат в себе слово «error». Не беспокойтесь об этом. Этот текст носит информационный характер – он не означает что есть проблемы с AutoCAD или вашим плагином.
Как только AutoCAD будет готов, загрузите плагин с помощью команды NETLOAD, как в 1 уроке. Однако, поскольку сейчас вы проводите отладку, Visual Studio Community создал «отлаженую» версию вашего .NET плагина DLL. Если вы сохранили свой проект в C:\test, то путь для загрузки бует:
C:\test\KeepAttributesHorizontal\KeepAttributesHorizontal\bin\Debug\KeepAttributesHorizontal.dll
Помните, что DLL, загруженный в 1-ом уроке, находилась в папке bin\Release. Когда вы создадите окончательную версию вашего DLL-плагина, который вы хотите предоставить своим пользователям и клиентам Visual Studio создаст версию для релиза. Visual Studio оптимизирует скомпилированный код с сборке для релиза, чтобы он работал быстрее и занимал меньше памяти. Когда вы хотите отладить свой код, Visual Studio создаёт отладочную версию вашего DLL плагина. Версия для отладки не оптимизирована в плане скорости/памяти, а также содержит дополнительную информацию, которую использует отладчик, чтобы рассказать вам о том, что происходит при запуске кода.
Теперь откройте тестовый файл BlocksWithAttributes.dwg
Контрольные точки.
Теперь ваш DLL плагин готов к отладке. Но прежде чем вы запустите команду KEEPSTRAIGHT, вы должны сообщить отладчику, где вы хотите, чтобы он остановился во время выполнения кода. Для того используются контрольные точки.
В Visual Studio дважды щёлкните мышью по MyCommands.vb в обозревателе решений, чтобы отобразить код и щёлкнуть в любом месте строки:
Public Shared Sub ImplementOverrule()
Далее выберите Toggle Breakpoint в меню Debug (или нажмите F9).

Теперь эта линия будет выделена красным цветом, а с краю появится красный круг, показывающий, что вы установили контрольную точку на этой строке:

Установите контрольную точку для функции TransformBy таким же образом:
Public Overrides Sub TransformBy(ByVal entity As Entity,
ByVal transform As Matrix3d)
Когда AutoCAD обращается к этим методам в вашем коде, отладчик останавливается на этих строках и ждёт, пока вы скажете, что делать дальше.
Выполнение кода.
Теперь пришло время вызвать вашу команду. Введите KEEPSTRAIGHT в командной строке AutoCAD, а затем нажмите Enter. Далее запускается Visual Studio (если этого не произошло, запустите его при помощи иконки на рабочем столе Windows). Отладчик остановлен в ожидании, выделив жёлтым цветом и стрелкой в поле ниже сроки, которая будет выполнена далее. Атрибут CommandMethod сообщает AutoCAD, что он должен запустить ваш метод KEEPSTRAIGHT, поэтому отладчик остановился на контрольной точке, которую вы установили в начале этого метода.

Теперь вы готовы выполнить свой код. В меню отладки Visual Studio есть три способа выполнить свой код: Step Into; Step Over и Step Out. В основном вы будете использовать Step Over – он выполняет строку кода (выделенную жёлтым цветом) в отладчике, а затем переходит к следующей строке. Если строка кода, которая должна быть выполнена, вызывает метод, то Step Over выполняет весь метод. Если вы хотите выполнить вызываемый метод по одной строке за шаг, вы можете использовать Step Into; и вы можете использовать Step Out для перемещения назад (из метода) к коду, который вы первоначально отлаживали.

Так же, как и в меню Debug, вы можете найти значки Step Into, Step Over и Step Out на панели инструментов, а ещё каждая из них имеет сочетание горячих клавиш (F8, Shift + F8 и Ctrl + Shift + F8).

А сейчас нажмите на значок Step Over на панели инструментов. Отладчик перейдёт к следующей строке кода (игнорируя комментарии).

Эта строка является началом условного оператора. Код между If… Then и End If выполняется только в том случае, если логическое условие между If и Then определяется как True. Наведите указатель мыши на текст myOverrule. Появилась всплывающая подсказка с указанием значения переменной.

Чтобы отображать значения переменных, вы также можете щёлкнуть правой кнопкой мыши на переменной в вашем коде и выбрать Add Watch. Теперь переменная и её значение будет отображаться в окне Watch в нижней части экрана.

Отладчик сообщает вам, что значение myOverrule в данный момент отсутствует. Это и не удивительно, так как вы первый раз запустили функцию. На основе информации, сообщённой вам отладчиком, будет ли выполнятся код внутри оператора If?
Правильно – будет – так как myOverrule имеет значение Nothing и это True (истинно).
Просмотрите код шаг за шагом, останавливаясь на значениях и свойствах переменных, чтобы посмотреть, как они меняются по мере выполнения кода. Если вы захотите отключить построчную отладку, просто нажмите F5, чтобы перейти к следующей контрольной точке, – это нужно сделать, когда вы дойдёте до конца метода ImplementOverrule ().
Теперь вы закончили выполнение своей пользовательской команды, теперь пришло время отладить запуск программы. Если AutoCAD не запустился автоматически, запустите его с иконки на рабочем столе. Введите ROTATE, в командной строке и нажмите Enter, выберите блок и назначьте точку вращения.
Как только вы выберете точку вращения, отладчик должен дойти до контрольной точки переопределённого метода TransformBy. Просмотрите этот код, проверяя значения переменных по мере прохождения по коду:
– Обратите внимание на значение переменной, которое передаётся функции. Отладчик сообщает что тип AttributeReference – переменная типа Entity содержащая объект типа AttributeReference. Помните о том, что вы узнали о наследовании в третьем уроке.
– Наведите курсор мыши на переменную. Нажмите на значок «+» слева от значения переменной во всплывающей подсказке, чтобы развернуть её окно. Так можно запрашивать общедоступные свойства этого экземпляра класса Matrix3d, который сообщает вам значения для каждого элемента матрицы, а также систему координат, представляемую матрицей. (Не переживайте, если вы не понимаете матричную геометрию – здесь вы можете просматривать свойства переменных в отладчике).
– Проверьте значение свойства attRef.Rotation непосредственно перед и после выполнения этой строки кода.
Если вы нажмёте F5, то обнаружите что AutoCAD вызывает TransformBy (). Это связано с тем, что AutoCAD закрепляет объект – он преобразует вставленный блок каждый раз, когда вы перемещаете мышь. Нажмите на строку, в которой вы добавили контрольную точку для функции TransformBy (), и нажмите F9, чтобы отключить её. Нажмите F5 ещё раз, и отладчик отладчик отменит остановку AutoCAD. Завершите команду ROTATE, щёлкнув в окне чертежа, для выбора угла поворота.
Наконец, снова вызовите команду KEEPSTRAIGHT. Проверьте значение myOverrule в начале инструкции If и посмотрите, как отладчик идёт по другому пути через ваш код во второй раз, когда вы запускаете этот метод.
Когда закончите экспериментировать, выберите Stop Debugging в меню Debug, чтобы закрыть AutoCAD и завершить сеанс отладки.

Поздравляю! Теперь вы знаете как совершать отладку проекта в Visual Studio.
Дополнительное упражнение.
Чтобы потренироваться с процессом отладки, создайте новый проект плагина и вставьте нижеприведённый код в MyCommands.vb. Код основан на примерах, рассмотренных в уроке 3, для демонстрации концепций объектно-ориентированного программирования. Запустите новый проект ObjectOrientedSample.
– установите контрольную точку в начале метода Test ();
– запустите AutoCAD из отладчика;
– загрузите при помощи команды NETLOAD ObjectOrientedSample.dll из подпапки проекта bin\debug.
– Запустите команду RUNTEST в командной строке AutoCAD, а затем используйте операции отладки, которые вы изучили в этом уроке, для изучения исполнения кода и просмотра значения переменных.
Вот код:
Imports Autodesk.AutoCAD.Runtime

Namespace ObjectOrientedSample

Public Class MyCommands

<CommandMethod(“RunTest”)>
Public Sub Test()

Dim pt1 As Point = New Point
USe Step Into on the next line to step into SetLocation
pt1.SetLocation(10, 10)
Dim xVal1 As Integer = pt1.X
pt1.X = 9
Dim xVal2 As Integer = pt1.X

Dim pt2 As NewPoint = New NewPoint
SetLocation, X and Y are inherited from Point class
pt2.SetLocation(20, 20)
Dim xVal3 As Integer = pt2.X
pt2.X = 9
Z is new to the NewPoint class
pt2.Z = 12
Dim pt3 As Point = pt2
pt3 is variable of type Point, but holds an object of type NewPoint
End Sub

End Class

Public Class Point

Private mXCoord As Integer
Private mYCoord As Integer

Public Sub SetLocation(ByVal x As Integer, ByVal y As Integer)
Me.mXCoord = x
Me.mYCoord = y
End Sub

Public Property X() As Integer
Get
Return Me.mXCoord
End Get
Set(ByVal value As Integer)
Me.mXCoord = value
End Set
End Property

Public Property Y() As Integer
Get
Return Me.mYCoord
End Get
Set(ByVal value As Integer)
Me.mYCoord = value
End Set
End Property

End Class

Public Class NewPoint
Inherits Point

Private mZCoord As Integer

Public Property Z() As Integer
Get
Return Me.mZCoord
End Get
Set(ByVal value As Integer)
Don’t accept negative Z values
If value >= 0 Then
Me.mZCoord = value
End If
End Set
End Property

End Class

End Namespace

Урок третий: первый взгляд на код (перевод)

На этом занятии мы более подробно разберём код, написанный на первом занятии. Если вы новичок в программировании, на этом занятии вы познакомитесь с множеством концепций программирования (особенно если вы новичок в объектно-ориентированном программировании). Эти понятия подробно описаны в разделе Дополнительные Материалы в конце этого урока. Вы можете сначала прочитать их или обращаться к ним по ходу занятия.
Запустите Visual Studio и откройте проект. Мы разберём код от начала и до конца.
Ключевые слова
Когда вы смотрите на код в Visual Studio (и в примерах к этому уроку), первое что вы заметите – это раскрашенный текст: для удобного чтения Visual Studio Community изменяет цвет определённых слов в коде. Слова, выделенные синим цветом, называются ключевыми словами, которые могут быть использованы только в определённых ситуациях. Например, вы не можете объявить переменную с именем Imports, так как она зарезервирована для обозначения чего-то специфического в Visual Basic .NET. Просмотрите код в Visual Studio Community и обратите внимание на то, какие слова выделены синим цветом.
Пространство имён
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Первые строки кода начинаются с ключевого слова Imports. При работе с различными сборками библиотек в вашем проекте Visual Basic .NET, часто для различных классов используется одно и тоже имя, например, может быть несколько версий класса Point в различных библиотеках. Чтобы избежать конфликта имён, .NET предоставляет концепцию пространства имён. Пространство имён – это способ организовать классы, объединяя их логически и помогает идентифицировать класс, который вы хотите использовать.
Например, предположим, что в одном районе живут два мальчик с именем Джон. Одним из способов идентификации может быть использование фамилии. Но если у обоих мальчиков фамилия Смит, этого будет недостаточно. Тогда нужно использовать дополнительный идентификатор, например, школу, в которой они учатся. В синтаксисе .NET это будет выглядеть как SchoolA.Smith.John для одного и SchoolB.Smith.John для другого.
Таким образом, вы можете определять использование определённых классов в Visual Basic .NET. Ключевое слово Imports даёт вам прямой доступ к классам, содержащимся в включённом пространстве имён, что позволяет не вводить полное пространство имён при вводе имён классов. Это так же является причиной добавления различных классов пространства имён в список, представленный функцией IntelliSence.
Например, если бы вы не добавили пространство имён Autodesk.AutoCAD.Runtime, вам пришлось бы написать такую строку:
<CommandMethod(“KeepStraight”)>
как
<Autodesk.AutoCAD.Runtime.CommandMethod(“KeepStraight”)>
Добавление пространств имён экономит много времени затрачиваемого на ввод кода.
Ключевое слово Imports – это директива, указывающая компилятору Visual Basic .NET предоставить доступ к содержимому указанного пространства имён из кода в этом исходном файле.
Строка, следующая за директивами Imports, так же связана с пространствами имён.
Namespace HorizontalAttributes
Это определение пространства имён классов, созданных в DLL сборке плагина. В данном руководстве это не важно, но, если кто-то захочет использовать вашу сборку в своём проекте, он импортирует пространства имён, которые вы определили, так же, как вы импортировали различные пространства имён Autodesk.AutoCAD.
Обратите внимание, что существует пространство имён конечных элементов в нижней части MyCommands.vb – такое же, как для классов и подпрограмм.
Класс Commands
Public Class Commands

End Class
Всё в .NET основано на классах. В ходе занятия вы создали два класса: класс Commands – класс, определяющий пользовательскую команду AutoCAD; скоро мы перейдём к классу KeepStraightOverrule.
Класс ваших команд имеет одну переменную – myOverrule – который используется для хранения нашего класса KeepStraightOverrule.
Private Shared myOverrule As KeepStraightOverrule
Это похоже на переменные, которые вы видели раньше, за исключением ключевого слоя Shared. Это ключевое слово означает, что вам не нужно создавать экземпляр вашего класса для доступа к переменной. Аналогично, каждый экземпляр вашего класса, который вы создадите, будет иметь одинаковое значение для этой переменной. Если переменная не была обобщена (shared), то её значение может быть различным в каждом экземпляре класса. На данный момент не нужно беспокоиться об этих деталях.
Обобщённую переменную можно рассматривать как библиотеку. Библиотека содержит информацию, которую каждый может найти при помощи поиска. Обобщённая переменная содержит информацию, которую может найти каждый экземпляр данного класса.
Атрибут CommandMethod
<CommandMethod(“KeepStraight”)>
Треугольные скобки вокруг CommandMethod означают, что это атрибут. Атрибуты определяют определённые свойства (или атрибуты) для сборки или метода. Атрибут CommandMethod сообщает AutoCAD, что он должен запускать метод, который следует за ним, всякий раз, когда пользователь вводит команду KEEPSTRAIFGT в командную строку AutoCAD. Если вы замените «KEEPSTRAIGHT» на «FLURBLE», AutoCAD запустит код в ответ на запрос «FLURBLE».
Подпрограмма ImplementOverrule
Public Shared Sub ImplementOverrule()
If myOverrule Is Nothing Then
myOverrule = New KeepStraightOverrule
Overrule.AddOverrule(
RXClass.GetClass(GetType(AttributeReference)),
myOverrule, False)
End If
Overrule.Overruling = True
End Sub
Подпрограмма ImplementOverrule создаёт новый экземпляр класса KeepStraightOverrule и сохраняет его в переменной класса. Поскольку мы добавили атрибут CommandMethod к этой подпрограмме, AutoCAD вызовет этот код, когда пользователь вызовет вашу пользовательскую команду, и управление будет передано в AutoCAD в конце подпрограммы.
Обратите внимание, что вы использовали ключевое слово Shared, для этой подпрограммы так же как для переменной. Причина этого кроется в том, как AutoCAD обрабатывает классы, которые определяют пользовательские команды. Если подпрограмма с атрибутом CommandMethod не используется совместно, AutoCAD создаст новый экземпляр класса для каждого документа, в котором запускается пользовательская команда. Нам это не нужно, поэтому мы используем наш командный метод (и любые другие методы, свойства или переменные, которые ему нужны). Это означает, что AutoCAD не создаёт лишние экземпляры нашего класса. (Он вообще не должен создавать экземпляр класса чтобы использовать общие методы).
If…Then…End if – это ключевые слова, формирующие условное выражение. Условное выражение позволяет определить, какая часть вашего кода будет выполняться в зависимости от определённых логических условий. Мы рассмотрим условные выражения ещё раз в этом уроке.
Логическое условие – это выражение, которое может быть истинными или ложным. Например, «1+1=2» истинно, но «1+1=3» ложно; ещё пример: «Рыба может плавать» – истина, но «Кирпич плавает» – ложь.
В вашем коде, вы проверяете, создан ли экземпляр класса KeepStraightOverrule и назначили его переменной myOverrule. Если вы первый раз запускаете эту команду после загрузки AutoCAD, значит вы ещё не назначили переменную, поэтому «myOverrule is nothing» истинно, и код инструкции If выполняется. Если же вы запускали эту команду ранее, myOverrule уже хранит экземпляр класса, поэтому «myOverrule is nothing» ложно, а код в операторе If не выполняется.
API AutoCAD содержит чрезвычайно мощный набор классов под названием Overrules. Использование Overrules позволяет изменять поведение стандартного объекта AutoCAD; таких как линия, круг или атрибут блока. Код в выражении If создаёт новый экземпляр класса KeepStrsightOverrule, сохраняя его в myOverrule к классу атрибутов AutoCAD AttributeReference (это класс, который отвечает за атрибут вставки блока).
Последняя строка кода в подпрограмме находится вне оператора If, поэтому она выполняется каждый раз, когда пользователь запускает нашу команду. Он просто гарантирует, что система пернаправления AutoCAD включена.
Класс KeepStraightOverrule.
Следующая часть кода определяет другой класс, но на этот раз мы используем наследование.
Public Class KeepStraightOverrule
Inherits TransformOverrule

End Class
Перемещение или поворот объекта называется преобразованием, поэтому мы используем один из классов Overrule из API AutoCAD – TransformOverrule, чтобы изменить то, как ведёт себя наш атрибут при его преобразовании. API AutoCAD предоставляет нам набор классов Overrule, которые мы можем использовать, но разработчики API не могут знать, как именно мы хотим изменить стандартное поведение объекта. Поэтому они предоставляют нам набор классов Overrule, которые не делаю ничего. Мы добавляем наше стандартное поведение путём получения (наследования) из одного их этих классов и переопределения необходимых нам методов.
Когда AutoCAD хочет преобразовать объект, он вызывает метод TransformBy в экземпляре класса Entity, который он хочет преобразовать, поэтому вы переопределяете эту функцию в TransformOverrule и добавляете ей свой собственный вид поведения. Ключевое слово Overrides сообщает компилятору, что вы заменяете функцию, определяемой в родительском классе TransformOverrule, своей собственной реализацией.
Public Overrides Sub TransformBy(ByVal entity As Entity,
ByVal transform As Matrix3d)
MyBase.TransformBy(entity, transform)
Dim attRef As AttributeReference = entity
attRef.Rotation = 0.0
End Sub
Вы хотите остановить атрибут (класс AttributeReference) имеющий поворот, который отличается от положения параллельному оси X, поэтому сперва сообщите атрибуту AttribyteReference что необходимо запустить его метод TransformBy (MyBase.TransformBy), а затем установите значение Rotation равным 0, для AttributeReference (attRef.Rotation = 0.0).
Этот код также вводит концепцию подбора:
– AttributrReference выводится из Entity.
– TransformBy – это метод класса Entity, поэтому первый параметр, переданный функции TransformBy класса Overrule, имеет тип Entity (entity As Entity).
– Вращение – свойство AttribyteReference.
Как мы получаем доступ к свойству AttributeReference.Rotation, если наша переменная имеет тип Entity?
Ответ – через подбор. Вы можете присвоить экземпляр класса переменной, представляющей любой класс, который предшествует ей в иерархии наследования. Вы только переназначаете класс AttributeReference, поэтому вы знаете, что переменная объекта действительно должна хранить объект AttributeReference.Но пока вы используете параметра объекта в своём коде, вы можете получить доступ только к методам и свойствам класса Entity. Чтобы получить доступ к свойству наследуемого класса (AttributeReference), вы должны привести переменную к переменной нужного типа. В Visual Basic .NET вы можете сделать это просто объявив переменную переменной другого типа. Это вы делаете в строке:
Dim attRef As AttributeReference = entity
Иерархия наследования для атрибута AttributeReference следуюущая DBObject -> DBEntity -> DBText -> AttributeReference, поэтому вы можете аналогичным образом преобразовать переменную в DBObject или DBText.
Следует соблюдать осторожность при подборе, чтобы быть уверенным, что вы применяете переменные правильного типа. Если вы ошибётесь, ваш код приведёт к ошибке. Например, вы не можете использовать атрибут AttributeReference и Line если они не находятся в одной ветви наследования.
Ой! Это куча информации. Было бы легче пройти пробежать по коду по мере его запуска и посмотреть порядок выполнения каждой строки? К счастью это возможно – это называется отладка. Вы научитесь отладке в уроке 5.
Дополнительные материалы.
Объектно-ориентированное программирование.
Из предыдущего урока вы узнали, что программа представляет собой последовательность инструкций, которая сообщает компьютеру, как выполнять одну или несколько задач. Простые программы, обычно, состоят из последовательности или списка инструкций, работающих с переменными – данными, говорящими что происходит в программе по мере её выполнения. Но с увеличением сложности такие линейные последовательности инструкций (подход, также называемый процедурным программированием), могут стать неуправляемыми и в конечном итоге не подойдут для задач, для которых писался код.
Чтобы разрешить проблему сложности, было разработано объектно-ориентированное программирование (ООП), позволяющее по-разному структурировать исходный код, обеспечивая возможность включения его компонентов и повторного использования. ООП предлагает разрабатывать дискретные, многоразовые логические модули программирования, направленные на моделирование объектов из проблемной области и взаимосвязи между ними.
Хорошим примером является карта. Карту города можно рассматривать как модель или упрощённое представление о самом городе, предоставляющее абстрактную информацию, в которой вы нуждаетесь.
Ключом к хорошему объектно-ориентированному дизайну является моделирование элементов предметной области как отдельных объектов, отображающих соответствующее поведение вещей, которые они представляют и взаимодействия между ними.
Класс можно рассматривать как тип, который можно использовать для описания представления вещи. Класс может рассматривать как шаблон, который описывает детали объекта и используется для создания отдельных объектов. Таким образом, классы могут помочь определить общие характеристики объектов своего типа: атрибуты (свойства) и поведение (методы).
Объект является экземпляром класса. Это структурные блоки объектно-ориентированного программирования и могут рассматриваться как переменные – зачастую довольно сложные – которые включают в себя как данные, так и поведение.
Как пример, связь между классом и объектом просматривается в AutoCAD iFeatures. iFeature можно рассматривать как класс. Когда вы создаёт экземпляр iFeature, этот экземпляр может рассматриваться как объект. iFeature это модель или шаблон: каждый экземпляр iFeature имеет набор параметров, определённых iFeature, но имеет разные значения этих параметров. Например, они могут иметь разную длину или ширину.
Классы.
Основой объектно-ориентированного программирования является класс. Класс может рассматривать как шаблон, который описывает детали объекта и используется для создания отдельных объектов. Таким образом, классы могут помочь определить общие характеристики объектов своего типа: атрибуты (свойства) и поведение (методы).
API AutoCAD .NET является объектно-ориентированным, и представляет части AutoCAD, файл DWG и геометрию в DWG файле как набор классов. Вот некоторые классы, которые вы найдёте в API AutoCAD .NET:
– Класс Document – представляет собой документы, открываемые в приложении AutoCAD.
– Класс Database – представляет собой файл DWG просматриваемый в документе.
– Класс Line – представляет собой линии на чертеже.
– Класс Circle – представляет собой окружности на чертеже.
Объект это, экземпляр класса. Это структурные блока объектно-ориентированного программирования и могут рассматриваться как переменные – иногда довольно сложные – которые содержат как данные, так и взаимодействия.
Например, на вашем чертеже множество линий. Каждая линия имеет свою начальную и конечную точку (и цвет, слой, тип линии, вес линии и т.д.), и поэтому каждая линия на чертеже будет представлена собственным экземпляром класса Line в API. Каждая линия — это линейный объект.

Вы будете пользоваться классами двумя способами года будете использовать AutoCAD .NET API. Вы будете использовать предопределённые классы, предоставленные API AutoCAD .NET и NET. Framework, и вы создадите ваши собственные классы для представления логических объектов, используемых в ваших плагинах. Давайте посмотрим, как вы определяете класс в Visual Basic .NET.
Важной концепцией объектно-ориентированного программирования является наследование, которое позволяет настроить или расширить существующий класс, а не писать собственный класс с нуля. Мы затронули эту концепцию ранее в этом уроке и рассмотрим её более подробно позднее.
Следующий фрагмент кода показывает пример простого объявления класса в Visual Basic .NET. При изучении этого вы более подробно ознакомитесь с синтаксисом языка Visual Basic .NET.
Public Class Point
Private mXCoord As Integer
Private mYCoord As Integer

Public Sub SetLocation(ByVal x As Integer, ByVal y As Integer)
Me.mXCoord = x
Me.mYCoord = y
‘ Do some calculations
End Sub
End Class
Первое слово, Public, даёт доступ к классу. Создание доступного класса означает, что любой программист может получить доступ к этому классу в своём собственном приложении. Так API AutoCAD определяет классы (такие как класс Line) для вас чтобы использовать в ваших плагинах. Остальные параметры будут внутренними (если они используются только в этом проекте) или частными (если их использовать только в том контексте, в котором они объявлены). По мере роста ваших навыков программирования вы узнаете, как лучше всего использовать уровни доступности. Пока вы учитесь, используйте доступные классы, если сомневаетесь.
Следующее слово, Class, сообщает компилятору что далее идёт объявление класса. Следующее слово, Point, это имя вашего класса. Обратите внимание, что в конце кода есть инструкция End Class. Весь код между Public Class Point и End Class – это исполнение класса.
Объявление переменных.
Переменные – это места для хранения информации, которую вы можете получить позже. Это программный эквивалент записи того, что вы не хотите забыть.
Private mXCoord As Integer
Private mYCoord As Integer
Эти две строки определяют два переменных члена класса. Переменные члены содержат данные, которые могут использоваться в разных частях кода вашего класса. Вы определяете переменные члены в одном месте и потом можете использовать их в разных местах. Они хранят информацию, заключённую в них, в течении всего жизненного цикла экземпляра класса, но каждый экземпляр класса может иметь различную информацию, хранящуюся в его переменных членах.
Ключевое слово Private применяется для установки доступности для этих переменных, чтобы к ним можно было получить доступ только из класса.
Слово Integer ссылается на тип «Integer», который сообщает компилятору, что вы хотите зарезервировать некоторое пространство для хранения целого числа. Наиболее распространёнными типами, обрабатываемыми Visual Basic .NET, являются числа с плавающей точкой (т. е. десятичные), целые числа и текст (известные как строки). mXCoord и mYCoord являются уникальными именами для идентификации этих переменных.
Примечание: по соглашению большинства программистов префикс имён переменных членов выглядит как `m` или `-m`.
Методы.
Следующий блок кода носит название – метод.
Public Sub SetLocation(ByVal x As Integer, ByVal y As Integer)
Me.mXCoord = x
Me.mYCoord = y
Do some calculations
End Sub
Каждый блок кода в классе, выполняющий определённую задачу (или действие), называется методом. Объявление метода начинается со слова Pyblic, так как мы хотим, чтобы тот, кто будет использоваться наш класс в собственном проекте, мог вызвать этот метод.
Следующее слово – Sub, что означает подпрограмму. Методы в Visual Basic .NET. могут быть либо подпрограммами, либо функциями. Мы обсудим разницу позднее. Обратите внимание, что ключевое слово Sub используется с ключевыми словами End Sub далее в коде. Как и для Class и End Class, выполнение метода содержится между этими строками.
Слово SetLocation – это уникальное имя, которое вы используете для идентификации и использования этого метода.
Часть инструкции, заключённая в скобки () содержит параметры метода. Параметр (или набор параметров) – это вход, предоставляемый методу для использования и работы. Вы должны передать два целочисленных параметра методу SetLocation, когда вы его вызываете. Целые числа, которые мы передаём, называются x и y – мы используем эти имена в коде внутри метода для доступа к параметрам в которые мы вошли.
Внутри метода содержаться такие строки:
Me.mXCoord = x
Me.mYCoord = y
Слово Me идентифицирует текущий экземпляр вашего класса. В первой строке вы получаете доступ к переменной – члену mXCoordэтого экземпляра и поэтому используете выражение Me.mXCoord. Символ «=» называется оператором присваивания и означает, что переменная слева от оператора будет иметь своё значение, изменённое на значение, указанное в справа от оператора. В этом случае вы устанавливаете значение переменной члена mXCoord текущего экземпляра вашего класса Point (используя Me) равного значению, переданному в метод через параметр x.
Следующая строка делает то же самое, но для mYCoord и y.
Строки, начинающиеся с апострофа «`», игнорируются Visual Basic .NET. С помощью них вы добавляете комментарии к вашему коду – комментарий – это текст, который вы пишете простым языком, чтобы описать, что делает ваш код. Вы также можете использовать комментарии, чтобы скрыть часть кода от компилятора, который вы не хотите встроить в свою DLL-версию .NET плагина.
Создание объектов класса.
Теперь у вас есть простой класс, определённый с помощью Visual Basic .NET. Следующий вопрос…
Как вы создаёте объекты этого класса?
Как обсуждалось ранее, объект является экземпляром класса. В приведённом ниже коде показано, как создать объект определённого класса. Эти строки обычно содержаться в реализации другого класса (почти весь код в программе Visual Basic .NET содержится в классах – вы увидите, как AutoCAD запускает ваш код позднее).
Dim pt As Point = New Point
pt.SetLocation(10,10)
В первой строке вы определили новую переменную с именем pt, которая определена как тип Point. Затем вы используете оператор присваивания, чтобы установить его начальное значение как новый экземпляр класса Point, созданный при помощи ключевого слова New. Во второй строке показано, как вызвать метод SetLocation (), передавая значения параметров (x=10 и y=10). Когда эта строка будет выполнена, управление будет передано в указанную выше функцию SetLocation, а она установит mXCoord и mYCoord в значение 10 для экземпляра класса Point, который вы создали и сохранили в переменной pt.
Подпрограммы и функции.
Метод SetLocation () был определён с использованием ключевого слова Sub. Мы определяем метод через Sub, если мы не хотим возвращать какую-либо информацию их этого метода. Но что, если вы хотите создать метод, который взял два параметра, выполнил некоторые вычисления с ними и вернул результат в код, который вызвал метод?
Тогда нужно использовать ключевое слово Function. Мы могли бы добавить функцию к нашему классу Point.
Public Function Multiply(ByVal a As Integer, ByVal b As Integer)As Integer
Return a * b
End Function
Мы изменили ключевое слово Sub на Function; добавление As Integer сообщает компилятору, что этот метод (функция) вернёт значение Integer вызывающему и Return a*b возвращает значение «а» умноженное на «b».
Мы бы вызвали эту функцию следующим образом:
Dim theResult As Integer = pt.Multiply(6 * 7)
После выполнения этой строки кода, переменная theResult будет иметь значение 42.
Обратите внимание, что theResult является пременной, он она не является переменной-членом. В отличие от переменной-члена (которая хранит запись о данных, которые она хранит, до тех пор, пока экземпляр класса, к которому он принадлежит, существует), theResult имеет область, ограниченную методом, в котором она определена, и к ней можно получить доступ только изнутри метода, в котором она содержится. Вот почему в определении theResult использовано ключевое слово Dim вместо Public или Private. Для переменных-членов вы будете использовать только Public или Private. И переменная внутри такой функции не запоминает её значения между вызовами функций (если вы не используете ключевое слово Static – но это выходит за рамки этого урока).
В этом уроке вы будете писать и вызывать подпрограммы и функции.
Свойства.
Основной особенностью Visual Basic .NET и других языков .NET является способность классов иметь свойства. Свойство – это просто способ обеспечения доступа к переменной-члену класса. Вы будете использовать свойства двумя способами:
– Вы получите доступ к свойствам для получения и установки информации для существующих объектов (например, настройки свойств StartPoint и EndPoint для объекта Line);
– Изредка вы будете создавать свойства в своих классах.
Начните с создания своего собственного свойства, а затем вы увидите, как использовать его вне вашего класса. Дописывая код, вот как можно добавить свойство к одному из классов:
Public Class Point
Private mXCoord As Integer
Private mYCoord As Integer

Public Sub SetLocation(ByVal x As Integer, ByVal y As Integer)
Me.mXCoord = x
Me.mYCoord = y
Do some calculations next
End Sub

Public Property X() As Integer
Get
Return Me.mXCoord
End Get
Set(ByVal value As Integer)
Me.mXCoord = value
End Set
End Property
End Class
Вышеприведённый код, выделенный жирным шрифтом, показывает, как вы можете добавить свойство своему классу, будь то для использования в собственном проекте или для использования другими программистами в своих проектах.
Объявление свойства начинается с ключевого слова Public – вы уже знаете, что оно означает. Затем мы сообщим компилятору, что свойство называется X и является целочисленным (Integer).
Get … End Get часть объявления свойства описывающая что происходит когда кто-то считывает значение свойства, а часть Set … End Set делает то же самое когда кто-то пишет или задаёт значение свойства.
В этом примере, наша реализация Set просто устанавливает значение mXCoord в значение параметра value. Обычно вы должны включать код для проверки того, что значение передано допустимо и не устанавливать переменную-член в новое значение если это не так.
Когда кто-то пытается получить доступ к вашему свойству для определённого объекта Point, выполняется функция Get-часть свойства исполняется, и оператор Return возвращает значение вашего внутреннего элемента данных – точно так же, как и для функции.
Давайте посмотрим, как это свойство можно использовать:
Dim pt As Point = New Point
pt.SetLocation(10, 10)
Dim xVal As Integer = pt.X
pt.X = 9
Вы начинаете с создания нового объекта Point, названного pt, как вы видели ранее.
Строки, выделенные жирным, показывают вам, как читать (или получать) свойство X вашего объекта pt, присваивая его значение переменной xVal, а затем как записать (или установить) его на новое значение 9.
Большое количество кода, который вы пишите, будет использовать такие свойства, как это показано в AutoCAD API и библиотеке классов .NET Framework.
Хорошая практика – сохранять переменные члены (или переменные данных) частными и разрешать доступ к ним за пределами вашего класса с использованием свойств. Это связано с тем, что ваше свойство может проверить, не пытается ли кто-то установить переменную член в действительное значение до того, как действительно установит значение члена-переменной (Аналогично, вы можете проверить, что переменная была правильно инициализирована, прежде чем передать её значение обратно вызывающему).
Например, если у вас есть переменная-член, которая содержит значение AutoCAD Color Index (ACI), вы не хотите разрешать кому-либо устанавливать его на значение больше 255.
Не менее важной причиной использования свойств является то, что они скрывают детали реализации вашего класса от посторонних.
Например, возможно вы изначально разработали класс, чтобы иметь переменную член, называемую «Area». Позже вы поняли, что вам не нужно сохранять значение «Area», потому что вы можете легко вычислить его, когда вам это нужно, используя переменные-члены «Length» и «Width». Если ваша переменная-член была общедоступной, тогда любой код, который использует ваш класс, был бы нарушен вашими изменениями. Если бы вы не внедрили свойство вместо этого, вы могли бы изменить свой Get для возвращения «Length*Width» вместо «Area».
Наследование.
В объектно-ориентированном программировании класс представляет собой просто набор данных (переменные-члены), методы и свойства (и события, которые мы не рассматриваем в этом учебнике). Методы и свойства класса содержат весь код, который выполняется при компиляции и запуске вашего плагина. Существует ещё одна чрезвычайно мощная концепция объектно-ориентированного программирования, которую вы должны знать, поскольку она составляет основу большей части API AutoCAD .NET. Это наследование.
Наследование – это метод, который позволяет настраивать или расширять (или специализировать) поведение существующего класса путём изменения или добавления его переменных-членов, методов и свойств. Самый подходящий способ объяснить это – объяснить, как AutoCAD использует классы для представления объектов в DWG-файле. Давайте посмотрим на иерархию наследования для классов AutoCAD Line и Arc.
Думайте, что наследование походе на эволюционное дерево. Более специализированные и сложные классы наследуют от («производные от») более простых менее специализированных классов, подобно тому, как более сложные организмы развиваются из более простых организмов (например, амфибии образовались из рыб, а рептилии эволюционировали из земноводных). Аналогичным образом, два сложных класса огут быть получены из одного и того же более простого класса, как и два современных животных могут иметь одного предка (например, люди и шимпанзе).
Всё что находится внутри чертежа AutoCAD – это своего рода DBObject. Это значит, что DBObject – это класс, который предоставляет данные, методы и свойства, общие для всего, что сохранено в DWG-файле. Например, DBObject имеет свойство ObjectId. ObjectId – уникальный идентификатор для каждого объекта в открытом чертеже.
Некоторые виды DBObject – это объекты, которые имеют графическое представление. Это подмножество BDObjects представлено классом Entity. Класс Entity получен из класса DBObject. Это означает, что Entity наследует все данные, методы и свойства из DBObject и добавляет новые данные, методы и собственные свойства. Например, Entity наследует свойство Objectld из DBObject. Каждый объект, который нарисован AutoCAD, имеет слой, поэтому одно из свойств, которое Entity добавляет к свойствам DBObject, является свойством Layer.
Некоторые типы Entity очень похожи – все они являются некоторого рода кривыми. Поэтому класс Curve наследует все данные, методы и свойства Entity и добавляет такие свойства, как StartPoint и EndPoint.
Наконец, Line и Arc – оба они типы кривых. Они наследуют все свойства от Curve и добавляют свои собственные. Например, Arc добавляет свойства StartAngle и EndAngle; Line добавляет свойство Delta (вектор, представляющий длину и направление линии).
Вот диаграмма, для лучшего понимания, показывающая только те свойства, о которых мы упоминали в приведённых выше примерах. Стрелки показывают направление наследования – переход к большей сложности / специализации.

Вы будете пользоваться наследованием в этом пособии, поэтому давайте посмотрим, как вы можете наследовать из класса Point, с которым вы только что работали. Класс Point – это простая двумерная точка (она имеет только координаты X и Y). Чтобы создать трёхмерный точечный класс, вы можете наследовать от вашего текущего класса Point и добавить дополнительную переменную член и свойство для представления своей координаты Z, например, так:
Public Class NewPoint
Inherits Point

Private mZCoord As Integer

Public Property Z() As Integer
Get
Return Me.mZCoord
End Get
Set(ByVal value As Integer)
Me.mZCoord = value
End Set
End Property
End Class
Когда мы создаём экземпляр этого нового класса, мы можем получить доступ ко всем свойствам, унаследованным от Point, а также к тем, которые добавлены NewPoint, например:
Dim pt As NewPoint = New NewPoint
pt.SetLocation(10, 10)
Dim xVal As Integer = pt.X
pt.X = 9
pt.Z = 12
Чтобы увидеть полное дерево наследования в API AutoCAD, откройте чертёж карты классов, который был установлен с вашим ObjectARX SDK ( \ classmap \ classmap.dwg). Большой, не правда ли?