Интерфейсы vs Делегаты.
От: _Winnie Россия C++.freerun
Дата: 04.12.05 18:08
Оценка:
Под интерфейсами имею в виду базовые классы с абстрактными виртуальными функциями, а под делегатами всякие Loki::Functor/boost::function/Winnie::Closure.

Что когда лучше использовать?
Когда виртуальные функции абсолютно не катят, и можно использовать только функторы?

Пока вижу только одно преимущество делегатов — их легко менять в runtime.
Но базовые абстрактные классы легче отписывать
(Гы, попробуйте отписать указатель на свой метод bind(&Foo::Bar, this) из std::list<boost::function>. Как это сделать?)
Есть еще "псевдо-преимущество" — можно подписать чужой класс на событие. Но это редко нужно, и легко реализуется своей виртуальной функцией — переходником.

Perfomance issues неинтересны, вроде бы они понятны.
(большие vtbl при использовании очень больших интерфейсов, динамическая аллокация памяти при использовании boost::function).

Еще в boost::function можно засунуть не только пары (объект, метод) но и любой функтор, это мне тоже не интересно, интересны именно (объект, метод).
Правильно работающая программа — просто частный случай Undefined Behavior
Re: Интерфейсы vs Делегаты.
От: ArtDenis Россия  
Дата: 04.12.05 18:21
Оценка:
_W>Пока вижу только одно преимущество делегатов — их легко менять в runtime.
_W>Но базовые абстрактные классы легче отписывать
Ну да? Нука привели пример

_W>(Гы, попробуйте отписать указатель на свой метод bind(&Foo::Bar, this) из std::list<boost::function>. Как это сделать?)

Вообще-то для меня делегаты — это не std::list<boost::function>, а именно boost::signals. Отписыватся в них можно элементарно.


Все плюсы и минусы функторов и интерфейсов познаёшь тогда, когда есть возможность использовать и то и другое (например, попробуй попрограммить немного на яве, чтобы прочувсвтвовать идею интерфейсов)
... << RSDN@Home 1.1.4 stable rev. 510>>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[2]: Интерфейсы vs Делегаты.
От: _Winnie Россия C++.freerun
Дата: 04.12.05 18:48
Оценка:
Здравствуйте, ArtDenis, Вы писали:

_W>>Пока вижу только одно преимущество делегатов — их легко менять в runtime.

_W>>Но базовые абстрактные классы легче отписывать
AD>Ну да? Нука привели пример

list.remove(this)

_W>>(Гы, попробуйте отписать указатель на свой метод bind(&Foo::Bar, this) из std::list<boost::function>. Как это сделать?)

AD>Вообще-то для меня делегаты — это не std::list<boost::function>, а именно boost::signals. Отписыватся в них можно элементарно.

Ага. А для меня boost::signals это ужас на крыльях свопа.
Попробуй написать логгинг использования динамической аллокации памяти. То, что он жрет пол-килобайта памяти на каждый функтор и делает кучу динамических аллокаций даже при вызове сингнала, для меня неприемлемо.

AD>Все плюсы и минусы функторов и интерфейсов познаёшь тогда, когда есть возможность использовать и то и другое (например, попробуй попрограммить немного на яве, чтобы прочувсвтвовать идею интерфейсов)


Расскажи
Правильно работающая программа — просто частный случай Undefined Behavior
Re[3]: Интерфейсы vs Делегаты.
От: _Winnie Россия C++.freerun
Дата: 04.12.05 18:56
Оценка:
Здравствуйте, _Winnie, Вы писали:

AD>>Все плюсы и минусы функторов и интерфейсов познаёшь тогда, когда есть возможность использовать и то и другое (например, попробуй попрограммить немного на яве, чтобы прочувсвтвовать идею интерфейсов)

_W>Расскажи

Программировал на Java в течении полугода в рамках полугодового курса у нас на факультете, писали простые учебные задачки, вроде "визуализация сортировки в нескольких параллельных потоках." Больше её не касался. Ну, интерфейсы. Что такого?
Правильно работающая программа — просто частный случай Undefined Behavior
Re[3]: Интерфейсы vs Делегаты.
От: ArtDenis Россия  
Дата: 04.12.05 19:33
Оценка:
AD>>Ну да? Нука привели пример
_W>list.remove(this)
Блин, точно

_W>Ага. А для меня boost::signals это ужас на крыльях свопа.

_W>Попробуй написать логгинг использования динамической аллокации памяти. То, что он жрет пол-килобайта памяти на каждый функтор и делает кучу динамических аллокаций даже при вызове сингнала, для меня неприемлемо.
Если честно, то меня реализация не особо заботит. Если понадобиться быстродействие — напишу свой велосипед.

AD>>Все плюсы и минусы функторов и интерфейсов познаёшь тогда, когда есть возможность использовать и то и другое (например, попробуй попрограммить немного на яве, чтобы прочувсвтвовать идею интерфейсов)

_W>Расскажи

А что рассказывать.
1. Негибкая эта система. Какждый раз надо писать реализацию интерфейса в виде класса и реализовывать какой-то там метод. Нельзя повесить обработчик разных событий на один метод (бывает нужно)
2. Читабельность кода в случае с делегатами гораздо выше (на мой взгляд)

IHMO. Идея использования интерфейсов для реализации обработчика события потому и возникла, что не было другого механизма для реализации. В C++ или в C# есть более удобное средство для этого дела. Почему бы его и не использовать?
... << RSDN@Home 1.1.4 stable rev. 510>>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[4]: Интерфейсы vs Делегаты.
От: _Winnie Россия C++.freerun
Дата: 04.12.05 21:19
Оценка:
Пишу либу. Хочу дать возможность юзеру кастомизировать что-то кэллбеком. Например, куда писать лог.

Как лучше сделать?

void MyLib::SetLoger( const boost::function<void(char *) > &);
void MyLib::SetLoger( ILogger * );
void MyLib::SetLoger( Closure <void(char *) > );
void MyLib::SetLoger( void *context,    void (*)(void*, char *) );


(Вместо логгирования может быть любая другая функция)
Правильно работающая программа — просто частный случай Undefined Behavior
Re[5]: Интерфейсы vs Делегаты.
От: _Winnie Россия C++.freerun
Дата: 04.12.05 22:09
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>Пишу либу. Хочу дать возможность юзеру кастомизировать что-то кэллбеком. Например, куда писать лог.


_W>Как лучше сделать?


_W>
_W>void MyLib::SetLoger( const boost::function<void(char *) > &);
_W>void MyLib::SetLoger( ILogger * );
_W>void MyLib::SetLoger( Closure <void(char *) > );
_W>void MyLib::SetLoger( void *context,    void (*)(void*, char *) );
_W>


_W>(Вместо логгирования может быть любая другая функция)


А если хочу так?
void MyLib::AddLoger( boost::function<void(char *) > );
void MyLib::AddLoger( ILogger * );
void MyLib::AddLoger( Closure <void(char *) > );
void MyLib::AddLoger( void *context,    void (*)(void*, char *) );

void MyLib::RemoveLoger( boost::function<void(char *) > );  //вот это вообще непонятно как реализовывать
void MyLib::RemoveLoger( ILogger * );
void MyLib::RemoveLoger( Closure <void(char *) > ); //тоже нетривиально, но я как аффтар Closure, могу кое-что сделать. 
void MyLib::RemoveLoger( void *context,    void (*)(void*, char *) );
Правильно работающая программа — просто частный случай Undefined Behavior
Re[6]: Интерфейсы vs Делегаты.
От: ArtDenis Россия  
Дата: 05.12.05 04:38
Оценка:
Hello, _Winnie! You wrote on Sun, 04 Dec 2005 22:09:17 GMT:

W> _W>Пишу либу. Хочу дать возможность юзеру кастомизировать что-то

W> кэллбеком. Например, куда писать лог.

Такой вопрос: а что будет логироваться в этой либе? Есть подозрения, что всё это можно реализовать без помощи калбэков.
Posted via RSDN NNTP Server 2.0
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re: Интерфейсы vs Делегаты.
От: bada  
Дата: 05.12.05 05:21
Оценка: :)
imho, на лицо некоторое непонимание основ.

Наследование (и виртуальные функции соответственно) является одним из основных инструментов, применяемых
в ОО парадигме. Использование виртуальных функций позволяет отделить абстракцию от ее конкретизаций/реализаций.
Таким образом наследование и виртуальные финкции — это фундаментальная фича языка С++ без которой невозможно
(читай очень геморно) писать объектно-ориентированные программы.

Функторы из области обобщенного программирования: очевидные применения — аргументы алгоритмов и т.п. Использование
функторов для формирования интерфейса неправильно (по крайней мере очень не в духе С++).

Здравствуйте, _Winnie, Вы писали:

_W>Под интерфейсами имею в виду базовые классы с абстрактными виртуальными функциями, а под делегатами всякие Loki::Functor/boost::function/Winnie::Closure.


_W>Что когда лучше использовать?

_W>Когда виртуальные функции абсолютно не катят, и можно использовать только функторы?

_W>Пока вижу только одно преимущество делегатов — их легко менять в runtime.

_W>Но базовые абстрактные классы легче отписывать
_W>(Гы, попробуйте отписать указатель на свой метод bind(&Foo::Bar, this) из std::list<boost::function>. Как это сделать?)
_W>Есть еще "псевдо-преимущество" — можно подписать чужой класс на событие. Но это редко нужно, и легко реализуется своей виртуальной функцией — переходником.

_W>Perfomance issues неинтересны, вроде бы они понятны.

_W>(большие vtbl при использовании очень больших интерфейсов, динамическая аллокация памяти при использовании boost::function).

_W>Еще в boost::function можно засунуть не только пары (объект, метод) но и любой функтор, это мне тоже не интересно, интересны именно (объект, метод).
Re[2]: Интерфейсы vs Делегаты.
От: ArtDenis Россия  
Дата: 05.12.05 08:14
Оценка: 2 (1)
Здравствуйте, bada, Вы писали:

B>imho, на лицо некоторое непонимание основ.


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

При помощи интерфейсов:
class CallbackInterface
{
public:
  virtual void do_call() = 0;
};


class ComeClass // Класс, который инициирует событие
{
  CallbackInterface * cbi;
    
    void do_something()    
    {
        //
        if (cbi) cbi->do_call(); // инициируем событие
        // 
    }
    
public:    
  void set_call_back_obj(CallbackInterface * cbi)
    {
        this->cbi = cbi;
    }
};

class Eventhandler : public /* или protected (чтобы не нарушать принцип Лисков)*/ CallbackInterface
{
  void init_events()
    {
      // Указываем, что обработчиком события явсляется наш объект
        some_class.set_call_back_obj(this);
    }

private:    
    // Обработчик события
    virtual void do_call()
    {

    }
};


При помощи функторов:
class ComeClass
{
    void do_something()    
    {
        //
        event(); // инициируем событие
        // 
    }

public:
  boost::signal<void()> event;
};

class Eventhandler
{
    boost::signals::scoped_connection scp_conn;
    
  void init_events()
    {
      // Указываем, что обработчиком события является this->do_event
        scp_conn = some_class.event.connect( boost::bind(&Eventhandler::do_event, this) );
    }

private:
    // Обработчик события
    void do_event()
    {

    }
};


Причём в последнем случае при помощи boost::signals::scoped_connection, объект отпишется от события после удаления автоматически. IMHO даже по объёму кдоа и читабельности делегаты (функторы) лучше
... << RSDN@Home 1.1.4 stable rev. 510>>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[3]: Интерфейсы vs Делегаты.
От: bada  
Дата: 05.12.05 08:41
Оценка:
Хорошо, прошу меня простить, видимо я не вник в контекст.

Оверквотинг убит. — Кодт
Re[2]: Интерфейсы vs Делегаты.
От: MaximE Великобритания  
Дата: 16.12.05 10:55
Оценка:
On Mon, 05 Dec 2005 05:21:41 -0000, bada <48802@users.rsdn.ru> wrote:

> imho, на лицо некоторое непонимание основ.

>
> Наследование (и виртуальные функции соответственно) является одним из основных инструментов, применяемых
> в ОО парадигме. Использование виртуальных функций позволяет отделить абстракцию от ее конкретизаций/реализаций.

OO парадигма — это не серебряная пуля. Полезность сильно преувеличена.

> Таким образом наследование и виртуальные финкции — это фундаментальная фича языка С++ без которой невозможно

> (читай очень геморно) писать объектно-ориентированные программы.

Это ерунда. Ознакомься с реализацией VFS в Lunux'e: OO на чистом C.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 2.0
Re: Интерфейсы vs Делегаты.
От: Smart_Ass  
Дата: 16.12.05 11:12
Оценка:
Что такое функтор ? По названию похоже что это объект-функция.
Re[2]: Интерфейсы vs Делегаты.
От: _nn_  
Дата: 16.12.05 11:16
Оценка:
Здравствуйте, Smart_Ass, Вы писали:

S_A>Что такое функтор ? По названию похоже что это объект-функция.

Функтор это объект к которому можно применить операцию скобки.
В С++ это может быть:
1. функция.
2. указатель на функцию.
3. объект класса с перегруженной операцией скобки.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Интерфейсы vs Делегаты.
От: Кодт Россия  
Дата: 16.12.05 11:48
Оценка:
Здравствуйте, MaximE, Вы писали:

>> imho, на лицо некоторое непонимание основ.

>>
>> Наследование (и виртуальные функции соответственно) является одним из основных инструментов, применяемых
>> в ОО парадигме. Использование виртуальных функций позволяет отделить абстракцию от ее конкретизаций/реализаций.

ME>OO парадигма — это не серебряная пуля. Полезность сильно преувеличена.


>> Таким образом наследование и виртуальные финкции — это фундаментальная фича языка С++ без которой невозможно

>> (читай очень геморно) писать объектно-ориентированные программы.

ME>Это ерунда. Ознакомься с реализацией VFS в Lunux'e: OO на чистом C.


Отвечу немного в сторону. По поводу колбэков.

Мы устанавливаем связь между двумя объектами — клиентом и исполнителем. Здесь есть 3 подзадачи
— установление связи: последнее слово здесь за исполнителем (а иногда и первое)
— обратный вызов
— разрыв связи

Если время жизни связи ограничено (до выхода из функции, куда колбек был передан как параметр) или управляется только исполнителем (подписка/отписка), то всё, что нужно клиенту — это функциональность обратного вызова. Можно через биндинг, можно через интерфейс.

А если разрыв связи может быть инициирован клиентом — то возникают вопросы
— извещения исполнителя
— управления временем жизни исполнителя

Можно, конечно, решить их с помощью ещё одного-двух колбеков... Однако, поскольку эти функции относятся к одному объекту — есть смысл их сгруппировать в единый интерфейс.

Причём необязательно, чтобы этот интерфейс был реализован напрямую исполнителем. Между ним и клиентом может располагаться объект-прокси/адаптер.
Перекуём баги на фичи!
Re[4]: Интерфейсы vs Делегаты.
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 16.12.05 13:12
Оценка:
Здравствуйте, bada, Вы писали.

1) Ограничь, пожалуйста, объем цитирования.
2) На этом форуме принято цитирование перед ответом, а не после.

Спасибо!
Re[3]: Интерфейсы vs Делегаты.
От: jazzer Россия Skype: enerjazzer
Дата: 18.12.05 10:13
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Это ерунда. Ознакомься с реализацией VFS в Lunux'e: OO на чистом C.


А также Motif
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Интерфейсы vs Делегаты.
От: Андрей Коростелев Голландия http://www.korostelev.net/
Дата: 18.12.05 22:53
Оценка:
Здравствуйте, bada, Вы писали:

B>imho, на лицо некоторое непонимание основ.


B>Наследование (и виртуальные функции соответственно) является одним из основных инструментов, применяемых

B>в ОО парадигме. Использование виртуальных функций позволяет отделить абстракцию от ее конкретизаций/реализаций.
B>Таким образом наследование и виртуальные финкции — это фундаментальная фича языка С++ без которой невозможно
B>(читай очень геморно) писать объектно-ориентированные программы.

Если уж лезть в основы, то наследование не является частью ООП-парадигмы.

Как наследование от абстрактной базы, так и использование делегатов позволяют определить протокол для взаимодействия с объектом (то есть набор сообщений, которые в данный момент имеют для объекта смысл).

Для первого подхода имеет место статическое определение объектом поддерживаемого протокола (и как следствие возможность проверки типов на этапе компиляции), для второго — возможность динамически изменять протокол объектом (тем не менее, сами сообщения должны быть известны в compile-time).
-- Андрей
Re: Интерфейсы vs Делегаты.
От: Аноним  
Дата: 19.12.05 15:26
Оценка:
Извиняюсь
Кто-то тут наежал на Жабу, но вы не совсем правы, она позволяет создавать анонимные внутрение классы, а для больших листенеров (интерфейсов, предназначенных для подключения к событиям) разработчики создают адаптеры (пустую реализацию)
Все это очень упрощает использование интерфейсов вместо функторов/делегатов
Сори если кого-то обидел
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.