Presentation is loading. Please wait.

Presentation is loading. Please wait.

Делегаты. Как созданные объекты могут посылать сообщения тем объектам, которые их породили? При программировании под Windows на С и C++ основное средство.

Similar presentations


Presentation on theme: "Делегаты. Как созданные объекты могут посылать сообщения тем объектам, которые их породили? При программировании под Windows на С и C++ основное средство."— Presentation transcript:

1 Делегаты

2 Как созданные объекты могут посылать сообщения тем объектам, которые их породили? При программировании под Windows на С и C++ основное средство для решения этой проблемы — это функция обратного вызова (callback function, или просто callback), которая основана на использовании указателей на функции в oпeративной памяти.

3 Делегаты Делегат выполняет те же действия, что и указатель на функцию, но способами гораздо более безопасными и лучше соответствующими принципам объектно- ориентированного программирования. Как и все в мире С#, делегат — это специальный класс. Любой делегат производится от единого базового класса — System.MulticastDelegate

4 Делегаты public delegate void PlayAcidHouse (object PaulQakenfold, int volume); На самом деле: public class PlayAcidHouse : System.MulticastDelegate { PlayAcidHouse(object target, int ptr); // Синхронный метод Invoke() public void virtual Invoke(object PaulOakenfold, int volume); // Асинхронная версия того же самого обратного вызова public virtual lAsyncResult Beginlnvoke (object PaulOakenfold, int volume, AsyncCallback cb, object o); public virtual void Endlnvoke(IAsyncResult result); }

5 Пример делегата // Класс Саг вновь изменился public class Car { // Новые переменные! private bool isDirty; // Испачкан ли наш автомобиль? private bool shouldRotate; // Нужна ли замена шин? // Конструктор с новыми параметрами public Car(string name, int max, int curr, bool dirty, bool rotate) {… isDirty = dirty; shouldRotate = rotate; } // Свойство для isDirty public bool Dirty { get { return isDirty; } set { isDirty = value;} } // Свойство для shouldRotate public bool Rotate {get { return shouldRotate; } set { shouldRotate = value; } }}

6 Пример делегата // Делегат - это класс, инкапсулирующий указатель на функцию. В нашем случае // этой функцией должен стать какой-то метод, принимающий в качестве параметра // объект класса Саг и ничего не возвращающий; public delegate void CarDelegate(Car с); Делегат может быть определен внутри другого класса // Помещаем определение делегата внутрь определения класса public class Car : Object ( // Теперь наш делегат получит служебное имя Car$CarDelegate, то есть станет // вложенным типом... public delegate void CarDelegate(Саг с);... }

7 Члены System.MulticastDelegate Таблица 5.2. Некоторые унаследованные члены делегатов Method - Это свойство возвращает имя метода, на который указывает делегат Target - Если делегат указывает на метод — член класса, то этот член возвращает имя этого класса. Если Target возвращает значение типа null, то делегат указывает на статический метод Combine() - Этот статический метод используется для создания делегата, указывающего на несколько разных функций GetlnvocationList() - Возвращает массив типов Delegate, каждый из которых представляет собой запись во внутреннем списке указателей на функции делегата Remove() - Этот статический метод удаляет делегат из списка указателей на функции

8 Применение CarDelegate // В классе Garage предусмотрен метод, принимающий CarDelegate в качестве параметра public class Garage { ArrayList theCars = new ArrayList(); // Набор машин в гараже public Garage() // Создаем объекты машин в гараже { theCars.Add(new car(“Viper“, 100, 0, true, false)); theCars.Add(new car("Fred“, 100, 0, false, false)); theCars.Add(new car("BillyBob“, 100, 0, false, true)); theCars.Add(new car(“Bart“, 100, 0, true, true)); theCars.Add(new car("Stan“, 100, 0, false, true)); }

9 Применение CarDelegate // Можно считать, что ргос - это эквивалент указателя на функцию public void ProcessCars(Car.CarDelegate proc) { // Интересно, а куда мы передаем наш вызов? Console.WriteLine(“***** Calling: {0} *****“, proc.Method.ToString()); // Еще одна проверка: вызываемый метод является статическим или обычным? if (proc. Target != null) Console. WriteLine("->Target: {0}“, proc.Target.ToString()): else Console. WriteLine("->Target Is a static method"); // Для чего это все затевалось: при помощи делегата вызываем метод // и передаем ему все объекты Саг foreach (car с in theCars) ргос(с); }

10 Применение CarDelegate // Гараж передает право выполнить всю работу этим статическим функциям - наверное, у него нет хороших механиков... public class CarApp { public static void WashCar(Car с) // Первый метод, на который будет указывать делегат {If (с.Dirty) { Console.WriteLine("Cleaning a car"); с.Dirty=false; } else Console.WriteLine("This car is already clean..."); ) public static void RotateTires(Car c) // Второй метод для делегата { if(c.Rotate) { Console.WriteLine(“Tires have been rotated"); c.Rotate=false; } else Console.WriteLine("Don't need to be rotated..."); } public static int Main(string[] args) { // Создаем объект Garage Garage g = new Garage(); // Моем все грязные машины g.ProcessCars(new Car.CarDelegate(WashCar)); II Меняем шины g.ProcessCars(new Car.CarDelegate (RotateTires)) ; return 0; }

11 Многоадресность Многоадресный делегат — это объект, который может содержать в себе сразу несколько указателей на функции. // Добавляем во внутренний список указателей делегата сразу два указателя на функции: public static int Main(string[] args) { // Создаем объект Garage Garage g = new Garage(): // Создаем два новых делегата Car.CarDelegate wash = new Car.CarDelegate(WashCar): Car.CarDelegate rotate = new Car.CarDelegate(RotateTires); // Чтобы объединить два указателя на функции в многоадресном делегате, // используется перегруженный оператор сложения (+). В результате создается новый // делегат, который содержит указатели на обе функции g.ProcessCars(wash + rotate); return 0: }

12 Многоадресность Изменяем функцию ProcessCars public void ProcessCars (CarDelegate proc) { // Куда мы передаем вызов? foreach (Delegate d in proc.GetInvocationList()) { Console.WriteLinet"***** Calling: " + d.method.ToString() + " *****");... }

13 Делегаты, указывающие на обычные функции // Статические функции перестали быть статическими и переместились // во вспомогательный класс public class ServiceDept { // Уже не статическая! public void WashCar(Car с) { if(c.Dirty) Console.WriteLine(“'Cleaning a car"); else Console.WnteLine(“This car is already clean...“); } // To же самое public void RotateTires(Car c) { If(c.Rotate) Console.WriteLine(“Tlres have been rotated"); else Console.WriteLine(“Don't need to be rotated..."); }

14 Делегаты, указывающие на обычные функции // Делегаты будут указывать на обычные методы класса ServiceDept public static int Main(string[] args) { // Создаем гараж Garage g = new Garage(); II Создаем отдел обслуживания ServlceDept sd = new ServiceDept(); // Гараж делегирует работу отделу обслуживания Car.CarDelegate wash = new Car.CarDelegate(sd.WashCar); Car.CarDelegate rotate = new Car.CarDelegate(sd.RotateTires); MulticastDelegate d = wash + rotate; // Обращаемся в гараж с просьбой сделать эту работу g.ProcessCars(Car.CarDelegate)d); return 0; }


Download ppt "Делегаты. Как созданные объекты могут посылать сообщения тем объектам, которые их породили? При программировании под Windows на С и C++ основное средство."

Similar presentations


Ads by Google