
ооп теория
.pdfКЛАСС 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