Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ооп теория

.pdf
Скачиваний:
21
Добавлен:
14.02.2015
Размер:
3.58 Mб
Скачать

КЛАСС Circle

Этот класс является потомком класса Ellipse:

using System;

using System.Drawing; namespace Shapes

{

///<summary>

///Класс Circle - потомок класса Ellipse.

///</summary>

public class Circle: Ellipse

{

public Circle( int radius,int x,

int y):base(radius,radius,x,y)

{

//Круг - это эллипс с равными полуосями (радиусом круга)

}

}

}

Здесь опять-таки проявляется мощь наследования. Потомок наследует все свойства и методы родителя. Ему остается только указать собственный конструктор объектов класса, да и в нем главное состоит в вызове конструктора родительского класса с передачей ему нужных аргументов.

Класс LittleCircle

Этот класс, задающие маленькие кружочки фиксированного радиуса, в свою очередь, является наследником класса Circle. Устроен он также чрезвычайно просто:

using System;

namespace Shapes

{

///<summary>

///Класс LittleCircle - потомок класса Circle.

///</summary>

public class LittleCircle:Circle

{

public LittleCircle(int x,int y): base(4,x,y)

{

// маленький круг радиуса 4

}

}

}

551

Класс Rect

Этот класс является еще одним прямым потомком класса Figure:

using System;

using System.Drawing; namespace Shapes

{

///<summary>

///Класс Rect - потомок класса Figure.

///</summary>

public class Rect:Figure

{

int sideA, sideB; Rectangle rect;

public Rect(int sideA,int sideB, int x, int y): base(x,y)

{

this.sideA = sideA; this.sideB = sideB; rect =Init();

}

public override void Show(Graphics g, Pen pen, Brush brush)

{

rect = Init(); g.DrawRectangle(pen,rect); g.FillRectangle(brush,rect);

}

public override Rectangle Region_Capture()

{

rect = Init(); return rect;

}

Rectangle Init()

{

int a =Convert.ToInt32(sideA*scale); int b =Convert.ToInt32(sideB*scale); int leftupX = center.X - a/2;

int leftupY = center.Y - b/2;

return( new Rectangle(leftupX,leftupY,a,b));

}

}

}

Класс Square

Квадрат - это частный случай прямоугольника. Соответствующий класс является потомком класса Rect:

using System; namespace Shapes

{

///<summary>

///Класс Square - потомок класса Rect.

///</summary>

public class Square:Rect

{

public Square(int side, int x, int y): base(side,side,x,y)

{

//квадрат - это прямоугольник с равными сторонами

552

}

}

}

Класс Person

Этот класс является прямым потомком класса Figure. Вместе с тем, класс является клиентом трех других классов семейства - Circle, Rect и LittleCircle,

поскольку элементы фигуры, составляющие человечка, являются объектами этих классов.

namespace Shapes

{

///<summary>

///Класс Person - потомок класса Figure,

///клиент классов Circle, Rect, LittleCircle.

///</summary>

public class Person:Figure

{

int head_h; Circle head; Rect body;

LittleCircle nose;

public Person(int head_h, int x, int y): base(x,y)

{

//head_h - радиус головы, x,y - ее центр. //остальные размеры исчисляются относительно //размера головы.

this.head_h = head_h;

head = new

Circle(head_h,x,y);

int body_x

= x;

int body_y

= y + 3*head_h;

int body_w

=2*head_h;

int body_h

= 4*head_h;

body = new

Rect(body_w, body_h, body_x,body_y);

nose = new

LittleCircle(x+head_h +2, y);

}

public override void Show(System.Drawing.Graphics g, System.Drawing.Pen pen, System.Drawing.Brush brush)

{

int h = Convert.ToInt32(head_h*scale); //head

int top_x = center.X - h; int top_y = center.Y - h;

g.DrawEllipse(pen, top_x,top_y, 2*h,2*h); g.FillEllipse(brush, top_x,top_y, 2*h,2*h); //body

top_y += 2*h;

g.DrawRectangle(pen, top_x,top_y, 2*h,4*h); g.FillRectangle(brush, top_x,top_y, 2*h,4*h); //nose

top_y -=h; top_x += 2*h;

g.DrawEllipse(pen, top_x,top_y, 8,8); g.FillEllipse(brush, top_x,top_y, 8,8);

}

553

public override System.Drawing.Rectangle Region_Capture()

{

int h = Convert.ToInt32(head_h*scale); int top_x = center.X - h;

int top_y = center.Y - h; return new

System.Drawing.Rectangle(top_x,top_y,2*h,2*h);

}

}

}

СПИСОК С КУРСОРОМ. ДИНАМИЧЕСКИЕ СТРУКТУРЫ ДАННЫХ

Добавим в проект классы, задающие динамические структуры данных.

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

using System; namespace Shapes

{

///<summary>

///Класс TwoWayList(G) описывает двусвязный список с

///курсором. Элементами списка являются объекты

///TwoLinkable, хранящие, помимо указателей на двух

///преемников, объекты типа G.Курсор будет определять

///текущий (активный) элемент списка. Класс будет

///определять симметричные операции по отношению к

///курсору.

///Конструкторы:

///Конструктор без параметров будет создавать пустой

///список

///Запросы:

///empty: require: true; возвращает true для пустого списка

///item: require: not empty(); возвращает активный элемент типа G;

///require: true; возвращает число элементов списка;

///count: count in[0,n] (count == 0) eqviv empty();

///index: require: not empty(); возвращает индекс активного элемента.

///search_res: require: true; возвращает true, если последний поиск был успешным.

///Команды:

///put_left(elem): require: true;

///ensure: добавить новый элемент (elem) слева от курсора;

///put_right(elem): require: true;

///ensure: добавить новый элемент (elem) справа от курсора;

///remove: require: not empty();

///ensure: удалить активный элемент;

///особо обрабатывается удаление последнего и единственного элементов

///операции с курсором:

///start: require: true;

///ensure: сделать активным первый элемент;

///finish: require: true;

554

///ensure: сделать активным последний элемент;

///go_prev: require: not (index = 1);

///ensure: сделать активным предыдущий элемент;

///go_next: require: not (index = count);

///ensure: сделать активным последующий элемент;

///go_i(i): require: (i in [1, count]);

///ensure: сделать активным элемент с индексом i;

///операции поиска:

///search_prev(elem): require: not (index = 1);

///ensure: сделать активным первый элемент elem слева от курсора;

///Успех или неуспех поиска сохранять в булевской

///переменной search_res

///search_next: require: not (index = count);

///ensure: сделать активным первый элемент elem справа от курсора;

///успех или неуспех поиска сохранять в булевской переменной

search_res

///</summary>

public class TwoWayList

{

public TwoWayList()

{

first = cursor = last = null; count = index = 0;

search_res = false; }//конструктор

///<summary>

///first, cursor, last - ссылки на первый,

///активный и последний элементы списка

///Запросы count, index search_res также

///реализуются атрибутами.

/// Запросы empty, item реализуются функциями

/// </summary>

protected TwoLinkable first, cursor, last; protected int count, index;

protected bool search_res;

//доступ на чтение к закрытым свойствам; public int Count

{

get

{

return(count);

}

}

public int Index

{

get

{

return(index);

}

}

public bool Search_res

{

get

{

return(search_res);

}

}

///<summary>

///require: true; возвращает true для непустого списка

///</summary>

///<returns></returns>

555

public bool empty()

{

return(first == null); }//empty

///<summary>

///require: not empty(); возвращает активный

///элемент типа G;

///</summary>

///<returns></returns>

public Figure item()

{

return(cursor.Item);

}//item

///<summary>

///require: true;

///ensure: добавить новый элемент (elem) слева

///от курсора;

///</summary>

///<param name="elem">Тип Figure играет роль

///родового типа G

///хранимого элемента elem</param>

public void put_left(Figure elem)

{

TwoLinkable newitem = new TwoLinkable(); newitem.Item = elem;

newitem.Next = cursor;

if (empty())

//список пуст

{

 

first = cursor = last = newitem; index =1; count = 1;

}

else

{

if (index == 1)

first =newitem;

else

cursor.Prev.Next = newitem; newitem.Prev = cursor.Prev; cursor.Prev =

newitem;

count++; index++;

}

}//put_right

///<summary>

///require: true;

///ensure: добавить новый элемент (elem) справа

///от курсора;

///</summary>

///<param name="elem">Тип Figure играет роль

///родового типа G

///хранимого элемента elem</param>

public void put_right(Figure elem)

{

TwoLinkable newitem = new TwoLinkable(); newitem.Item = elem;

newitem.Prev = cursor;

if (empty()) //список пуст

{

first = cursor = last = newitem; index =1; count = 1;

}

else

556

{

if (index == count) last =newitem;

else

cursor.Next.Prev = newitem;

newitem.Next = cursor.Next; cursor.Next =

newitem;

count++;

}

}//put_right

public void remove()

{

if(count == 1)

{

first = last = cursor = null; index=0;

}

else if(index==1)

{

first = cursor.Next; cursor.Prev = null; cursor = cursor.Next;

}

else if(index == count)

{

last = cursor.Prev; cursor.Next = null; cursor = cursor.Prev; index--;

}

else

{

cursor.Prev.Next = cursor.Next; cursor.Next.Prev = cursor.Prev; cursor = cursor.Next;

}

count--; }//remove

///операции с курсором:

///<summary>

///start: require: true;

///ensure: сделать активным первый элемент;

///</summary>

public void start()

{

cursor = first; index = 1; }//start

///<summary>

///finish: require: true;

///ensure: сделать активным последний элемент;

///</summary>

public void finish()

{

cursor = last; index = count; }//finish

///<summary>

///go_prev: require: not (index = 1);

///ensure: сделать активным предыдущий элемент;

///</summary>

public void go_prev()

557

{

cursor = cursor.Prev; index--; }// go_prev

///<summary>

///go_next: require: not (index = count);

///ensure: сделать активным последующий элемент;

///</summary>

public void go_next()

{

cursor = cursor.Next; index++; }// go_next

///<summary>

///go_i(i): require: (i in [1, count]);

///ensure: сделать активным элемент с индексом i;

///</summary>

///<param name="i"></param>

public void go_i(int i)

{

if(i >index)

while (i>index)

{

cursor = cursor.Next; index++;

}

else if(i<index)

while (i<index)

{

cursor = cursor.Prev; index--;

}

}// go_i

///операции поиска:

///<summary>

///search_prev(elem): require: not (index = 1);

///ensure: сделать активным первый элемент elem

///слева от курсора;

///</summary>

///<param name="elem">искомый элемент</param> public virtual void search_prev(Figure elem)

{

bool found = false;

while (!found && (index !=1))

{

cursor = cursor.Prev; index--; found = (elem == item());

}

search_res = found; }// search_prev

///<summary>

///успех или неуспех поиска сохранять в булевской

///переменной search_res

///search_next: require: not (index = count);

///ensure: сделать активным первый элемент elem

///справа от курсора;

///успех или неуспех поиска сохранять в булевской

///переменной search_res

///</summary>

///<param name="elem"></param>

public virtual void search_next(Figure elem)

{

bool found = false;

while (!found && (index !=count))

{

558

cursor = cursor.Next; index++; found = (elem == item());

}

search_res = found; }//search_next

}

}

Заметьте, класс подробно документирован. Для методов класса указываются предусловия и постусловия. Обратите внимание, в соответствии с принципами контрактного программирования клиент класса, прежде чем вызвать метод, должен проверить выполнимость предусловия, что повышает корректность работы системы в целом. Именно так и будет реализован вызов этих методов в классе формы, где осуществляется работа со списком.

КЛАССЫ ЭЛЕМЕНТОВ СПИСКА

Рассмотрим классы, описывающие элементы списков - элементы с одним и с двумя указателями:

using System; namespace Shapes

{

///<summary>

///Класс Linkable(T)задает элементы списка,включающие:

///информационное поле типа T - item

///ссылку на элемент типа Linkable - next

///Функции:

///конструктор new: -> Linkable

///запросы:

///Get_Item: Linkable -> T

///Get_Next: Linkable -> Linkable

///процедуры:

///Set_Item: Linkable*T -> Linkable

///Set_Next: Linkable*Linkable -> Linkable

///Роль типа T играет Figure

///</summary>

public class Linkable

{

public Linkable()

{

item =null; next = null;

}

///<summary>

///закрытые атрибуты класса

///</summary>

Figure item;

Linkable next;

///<summary>

///процедуры свойства для доступа к полям класса

///</summary>

559

public Figure Item{ get{

return(item);

}

set{

item = value;

}

}

public Linkable Next{ get{

return(next);

}

set{

next = value;

}

}

}//class Linkable

///<summary>

///Класс TwoLinkable задает элементы с двумя ссылками

///</summary>

public class TwoLinkable

{

public TwoLinkable()

{

prev = next = null;

}

///<summary>

///закрытые атрибуты класса

///</summary>

TwoLinkable prev, next;

Figure item;

///<summary>

///процедуры свойства для доступа к полям класса

///</summary>

public Figure Item

{

get

{

return(item);

}

set

{

item = value;

}

}

public TwoLinkable Next

{

get

{

return(next);

}

set

{

next = value;

}

}

public TwoLinkable Prev

{

get

{

560