Универсальность. Классы с родовыми параметрами
Под универсальностью (genericity) понимается способность класса объявлять используемые им типы как параметры. Класс с параметрами, задающими типы, называется универсальным классом (generic class). Универсальными могут быть как классы, так и все их частные случаи - интерфейсы, структуры, делегаты, события. class MyClass {...}
Класс с универсальными методами class Change{ static public void Swap (ref T x1, ref T x2) { T temp; temp = x1; x1 = x2; x2 = temp; } public void TestSwap(){ int x1 = 5, x2 = 7; Change.Swap (ref x1, ref x2); string s1 = "Саша", s2 = "Павел"; Change.Swap (ref s1, ref s2); Person pers1 = new Person("Савлов", 25, 1500); Person pers2 = new Person("Павлов", 35, 2100); Change.Swap (ref pers1, ref pers2); }
Два основных механизма объектной технологии Наследование позволяет специализировать операции класса, уточнить, как должны выполняться операции. Универсализация позволяет специализировать данные, уточнить, над какими данными выполняются операции.
Этап проектирования: абстрактный класс с абстрактными типами Наследование: уточняется представление данных; задается или уточняется реализация методов родителя
Родовое порождение: уточняются типы данных; порождается класс путем подстановки конкретных типов
Стек abstract public class GenStack { abstract public T item(); abstract public void remove(); abstract public void put(T t); abstract public bool empty(); }
Стек на односвязном списке public class OneLinkStack : GenStack { public OneLinkStack() { top = null; } GenLinkable top ; //ссылка на вершину стека public override T item() { return (top.Item); } public override bool empty() { return (top == null); } public override void put(T elem) { GenLinkable newitem = new GenLinkable (); newitem.Item = elem; newitem.Next = top; top = newitem; } public override void remove() {top = top.Next; } } public class GenLinkable { public T Item; public GenLinkable Next; public GenLinkable() { Item = default(T); Next = null; } }
Стек в виде массива public class ArrayUpStack : GenStack { int SizeOfStack; T[] stack; int top; public ArrayUpStack(int size) { SizeOfStack = size; stack = new T[SizeOfStack]; top = 0; } public override void put(T x) { stack[top] = x; top++; } public override void remove() { top--; } public override T item() { return (stack[top-1]); } public override bool empty() { return (top == 0); } }
public void TestPerson() { OneLinkStack stack1 = new OneLinkStack (); OneLinkStack stack2 = new OneLinkStack (); ArrayUpStack stack3 = new ArrayUpStack (10); ArrayUpStack stack4 = new ArrayUpStack (7);... }
Ограниченная универсальность Ограничение наследования. Это основный вид ограничений, указывающий, что тип T является наследником некоторого класса и ряда интерфейсов. Следовательно, над объектами типа T можно выполнять все операции, заданные базовым классом и интерфейсами. where T: BaseClass, I1,...Ik. Ограничение конструктора. Это ограничение указывает, что тип T имеет конструктор без аргументов и, следовательно, позволяет создавать объекты типа T. where T: new(). Ограничение value/reference. Это ограничение указывает, к значимым или к ссылочным типам относится тип T. Для указания значимого типа задается слово struct, для ссылочных - class. where T: struct.
public class Father { } public class Base{ public void M1() { } public void M2() { } } public class Child : Father where T1:Base, IEnumerable, new() where T2:struct, IComparable {}
Пример: список с возможностью поиска элементов по ключу class Node where K: IComparable { public Node() { next = null; key = default(K); item = default(T); } public K key; public T item; public Node next; }
public class OneLinkList where K : IComparable { Node first, cursor; public void start(){ cursor = first; } public void finish(){ while (cursor.next != null) cursor = cursor.next; } public void forth(){ if (cursor.next != null) cursor = cursor.next; } public void add(K key, T item){ Node newnode = new Node (); newnode.key = key; newnode.item = item; if (first == null) { first = cursor= newnode; } else { newnode.next = cursor.next; cursor.next = newnode; }
public bool findstart(K key){ Node temp = first; while (temp != null) { if (temp.key.CompareTo(key) == 0) { cursor=temp; return(true); } temp= temp.next; } return (false); } public void TestConstraint(){ OneLinkList list1 = new OneLinkList (); OneLinkList list2 = new OneLinkList (); … }
Родовое порождение класса. Предложение using using IntStack = Generic.OneLinkStack ; public void TestIntStack(){ IntStack stack1 = new IntStack(); IntStack stack2 = new IntStack(); IntStack stack3 = new IntStack();... }
Частные виды классов Универсальные структуры public struct Point { T x, y;//координаты точки } Универсальные интерфейсы IComparable Универсальные делегаты class WithDelegate { public delegate T Del(T a, T b);... } WithDelegate.Del del1 = new WithDelegate.Del(Program.max2); // del1= this.max2; в С# 2.0 public delegate T FunTwoArg (T a, T b);