На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: ANDLL, ALXR
Страницы: (20) « Первая ... 11 12 [13] 14 15 ...  19 20 все  ( Перейти к последнему сообщению )  
> Как вы относитесь к паскалю? , (есть гипотеза)
   
Как вы относитесь к паскалю?
Гости не могут просматривать результаты голосования.
Гости не могут голосовать 
    Цитата D_KEY @
    В питоне происходит линеаризация иерархии, если что.
    Линеаризация линеаризацией, но как бы ты выкарабкивался, если бы память объекта базового класса была частью памяти унаследованного? В результате с линеаризацией или без у тебя всё равно оставалась бы проблема двух экземпляров класса в вершине ромба. В C++ она худо-бедно решается виртуальным наследованием, в питоне всё наследование получается виртуальным, поэтому нет хотя бы этой части проблемы. Плюс днамическая утиная типизация, благодаря чему нет необходимости преобразовывать ссылки к ссылкам на базовый тип.
      Зачем вообще привлекать терминологию c++? В Питоне нет обычного и виртуального наследования, как это понимается в c++. Проблема ромба просто устраняется за счёт линеаризации.
        Цитата korvin @
        Что ж так?

        а зачем?
          Цитата Shaggy @
          например так:
          Т.е. всё-таки агрегировать... досадно.
            Цитата Shaggy @
            а зачем?

            А как ты в типе параметра метода указываешь, что он должен удовлетворять нескольким интерфейсам? Т.е. например

            ExpandedWrap disabled
              interface ReadWriter extends Reader, Writer {}
               
              ...
              public void someMethod(ReadWriter x) { ... }
              Цитата D_KEY @
              ...где ромб можно разруливать не только по классам, но и по полям...
              Я-таки нашёл свой эксперимент.
              Внимание! предупреждаю:
              ExpandedWrap disabled
                struct NullType {};
                 
                template <typename L, bool V, typename R>                       struct TList;
                template <typename T, bool V1, typename L, typename R, bool V2> struct TList<T, V1, TList<L, V2, R> >
                {
                  typedef T               Head;
                  typedef TList<L, V2, R> Tail;
                };
                template <typename T, bool V>                                   struct TList<T, V, NullType>
                {
                  typedef T        Head;
                  typedef NullType Tail;
                };
                template <typename T, bool V1, typename L, typename R, bool V2> struct TList<TList<L, V2, R>, V1, T>;
                template <typename T, bool V>                                   struct TList<NullType, V, T>;
                 
                template <typename T, size_t N>                     struct GetType;
                template <typename L, bool V, typename R, size_t N> struct GetType<TList<L, V, R>, N>
                {
                  typedef typename GetType<R, N-1>::result result;
                };
                template <typename L, bool V, typename R>           struct GetType<TList<L, V, R>, 0>
                {
                  typedef L result;
                };
                 
                template <typename T, size_t I> struct Item { T node; Item(): node(T()) {} };
                 
                template <typename T, size_t N, typename Z>             struct GenHierarchy;
                template <typename L, typename R, size_t N, typename Z> struct GenHierarchy<TList<L, false, R>, N, Z> :
                                                                             Item<L, N>, GenHierarchy<R, N+1, Z>
                {
                };
                template <typename L, typename R, size_t N, typename Z> struct GenHierarchy<TList<L, true,  R>, N, Z> :
                                                                     virtual Item<L, N>, GenHierarchy<R, N+1, Z>
                {
                };
                template <typename L, size_t N, typename Z>             struct GenHierarchy<TList<L, false, NullType>, N, Z> :
                                                                     Item<L, N>, virtual GenHierarchy<NullType, N+1, Z>
                {
                  typedef Z result;
                };
                template <typename L, size_t N, typename Z>             struct GenHierarchy<TList<L, true,  NullType>, N, Z> :
                                                             virtual Item<L, N>, virtual GenHierarchy<NullType, N+1, Z>
                {
                  typedef Z result;
                };
                template <size_t N, typename Z>                         struct GenHierarchy<NullType, N, Z> {};
                 
                template <typename T> struct GenerateTree: GenHierarchy<T, 0, T>
                {
                  template <size_t I>
                  typename GetType<T, I>::result& field()
                  {
                    return static_cast<Item<typename GetType<T, I>::result, I>&>(*this).node;
                  }
                };
                 
                template <size_t I, typename Gen>
                typename GetType<typename Gen::result, I>::result& field(Gen& gen)
                {
                  return static_cast<Item<typename GetType<typename Gen::result, I>::result, I>&>(gen).node;
                }
              Список типов создаётся так: тип поля (получает номер 0), признак разделения (true/false), следующий элемент списка (поле получит номер на 1 больше) ... или NullType (конец списка). Пример:
              ExpandedWrap disabled
                typedef TList<int,     false,                                // struct { separated int     0;
                        TList<int,     true,                                 //          shared    int     1;
                        TList<float,   false,                                //          separated float   2;
                        TList<wchar_t, false,                                //          separated wchar_t 3;
                        TList<int,     false,                                //          separated int     4;
                        TList<float,   true, NullType> > > > > > TypeList;   //          shared    float   5; };
              На его основе создаётся тип объекта(ов), который просто используется в качестве базы, когда и где надо. Пример:
              ExpandedWrap disabled
                struct Right: GenerateTree<TypeList> {};
                struct Left : GenerateTree<TypeList> {};
                 
                struct Tuple: Right, Left {};
              Тут в виду прямых множественных предков базы определены разными, но совпадающими типами Right и Left, ибо одинаковые непосредственные базы в Плюсах запрещены. Но хотя бы один будет опосредованным, они могут быть одинаковыми.
              Для доступа к совмещаемым полям можно использовать последнюю функцию field<N>(), указав номер поля в N и экземпляр структуры в параметре. Для совмещаемых этого достаточно, однако для отделённых следует заботиться о разрешении неоднозначности и использовать метод GenerateTree<>::field<N>() нашего экземпляра. Пример:
              ExpandedWrap disabled
                template <typename Dst, typename Src>
                Dst& select(Src& src)
                {
                  return static_cast<Dst&>(src);
                }
                 
                int main()
                {
                  Tuple tuple;
                 
                  select<Right>(tuple).field<0>() = 123;
                  select<Right>(tuple).field<1>() = 456;
                  select<Right>(tuple).field<2>() = 789.147f;
                  select<Right>(tuple).field<3>() = L'q';
                  select<Right>(tuple).field<4>() = 258;
                  select<Right>(tuple).field<5>() = 147.789f;
                  select<Left >(tuple).field<0>() = 321;
                  select<Left >(tuple).field<1>() = 654;
                  select<Left >(tuple).field<2>() = 987.369f;
                  select<Left >(tuple).field<3>() = L'Q';
                  select<Left >(tuple).field<4>() = 852;
                  select<Left >(tuple).field<5>() = 963.987f;
                 
                  std::wcout<< select<Right>(tuple).field<0>() << '\t'
                            << select<Right>(tuple).field<1>() << '\t'
                            << select<Right>(tuple).field<2>() << '\t'
                            << select<Right>(tuple).field<3>() << '\t'
                            << select<Right>(tuple).field<4>() << '\t'
                            << select<Right>(tuple).field<5>() << '\n'
                            << select<Left >(tuple).field<0>() << '\t'
                            << select<Left >(tuple).field<1>() << '\t'
                            << select<Left >(tuple).field<2>() << '\t'
                            << select<Left >(tuple).field<3>() << '\t'
                            << select<Left >(tuple).field<4>() << '\t'
                            << select<Left >(tuple).field<5>() << std::endl;
                 
                  field<1>(tuple) = 456;
                  field<5>(tuple) = 147.789f;
                 
                  std::wcout<< field<1>(tuple) << '\t'
                            << field<5>(tuple) << '\n'
                            << sizeof tuple    << std::endl;
                }
              Жёстко, но работает. Но ни разу не понадобилось, нето так долго б не искал.
                Цитата korvin @
                А как ты в типе параметра метода указываешь, что он должен удовлетворять нескольким интерфейсам?

                никак, нет необходимости
                все нужные интерфейсы запрашиваются явно
                  D_KEY, ты же сам решил питон с C++ сравнить. Без деталей реализации сравнение бессмысленно, я и написал, что реализация наследования в питоне слишком отличается от таковой в C++. И попытка реализации в C++ чего-то подобного питоновскому обойдётся слишком дорого.
                    Сравнение без деталей реализации не бессмысленно, оно показывает разницу подходов и принципов, лежащих в основе языков.
                      Цитата Shaggy @
                      все нужные интерфейсы запрашиваются явно

                      В смысле так:
                      ExpandedWrap disabled
                        procedure DoSomething (x: InterfacedObject);
                        var
                          r: Reader;
                          w: Writer;
                        begin
                          if not (x is Reader) then Exit;
                          if not (x is Writer) then Exit;
                          r := x as Reader;
                          w := x as Writer;
                          ...

                      что ли?
                        ExpandedWrap disabled
                          r:=x as Reader;
                           
                          // или
                           
                          if Supports(x,Reader,r)
                          then
                          Ну я так и написал. А если интерфейсов будет больше? Как-то это криво и неудобно.
                            Цитата korvin @
                            Ну я так и написал

                            нет
                            1. is с интерфейсами не работает
                            2. даже если бы работала, зачем делать две проверки вместо одной?
                            Цитата korvin @
                            А если интерфейсов будет больше? Как-то это криво и неудобно

                            это такая агитация за "god/magic method"?
                              Цитата Shaggy @
                              нет
                              1. is с интерфейсами не работает

                              Да не суть важно.

                              Цитата Shaggy @
                              2. даже если бы работала, зачем делать две проверки вместо одной?

                              Т.е. при присваивании
                              ExpandedWrap disabled
                                r := x as Reader;

                              происходит проверка? А если x не реализует Reader, что произойдет? Выброс исключения?

                              Цитата Shaggy @
                              это такая агитация за "god/magic method"?

                              Нет, при чем тут это?

                              Где тут god'овость?

                              ExpandedWrap disabled
                                interface Reader {
                                    Read(...)
                                }
                                 
                                interface Writer {
                                    Write(...)
                                }
                                 
                                interface Opener {
                                    Open() : Error
                                }
                                 
                                interface Closer {
                                    Close()
                                }
                                 
                                interface OpenReadWriteCloser { Open, Reader, Writer, Closer }
                                 
                                procedure DoSomething(x : OpenReadWriteCloser) Error {
                                    var request, response : Data
                                    if err := x.Open(); err != nil {
                                        return err
                                    }
                                    delay x.Close()
                                    x.Read(&request)
                                    ...
                                    x.Write(response)
                                }

                                Цитата korvin @
                                происходит проверка? А если x не реализует Reader, что произойдет? Выброс исключения

                                да
                                supports возвращает false
                                а с помощью queryinterface можно и причину узнать
                                используй что тебе удобнее, но не всё же сразу

                                Цитата korvin @
                                Где тут god'овость?

                                если у тебя все интерфейсы содержат по одному методу, тогда понятно такое их количество
                                я как-то привык создавать по интерфейсу на задачу, а не на каждое действие
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (20) « Первая ... 11 12 [13] 14 15 ...  19 20 все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0.1156 ]   [ 19 queries used ]   [ Generated: 27.07.26, 11:51 GMT ]