На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (495) « Первая ... 139 140 [141] 142 143 ...  494 495  ( Перейти к последнему сообщению )  
> Delphi vs C++ vs C# , ну и Java немножко, где-то ближе к старшему байту номеров страниц
    korvin, и вывод будет
    ExpandedWrap disabled
      A.f
      B.f
      B.f
      B.g

    ?
    Странно, не ожидал :)
      Цитата D_KEY @
      1. У той, "тип" которой ты описываешь своим интерфейсом
      2. Ты не понял о чем я :) Дело не в том, чтобы задать сущности явное имя, дело в создании лишней сущности тогда, когда она не нужна.

      так еще раз: о какой сущности идет речь? интерфейсом я определяю, что все объекты, для которых реализованы методы foo и bar являются объектами типа I
        Цитата korvin @
        тем, что шаблон никак не может проверить, реализует ли переданный ему тип нужный интерфейс (методы foo и bar), потому и получаем ошибки уже после раскрытия шаблона в кучу кода.

        Компилятор просто скажет, что тип не реализует данный метод.
        Цитата korvin @
        или таки может?

        Можно.
          Цитата MyNameIsIgor @
          korvin, и вывод будет
          ExpandedWrap disabled
            A.f
            B.f
            B.f
            B.g

          ?
          Странно, не ожидал :)

          я ж говорю, проверить не могу, но должен быть такой. а что тут странного? задача сводится всего лишь к перекрытию метода предка и приведению объекта-потомка к типу объекта предка, чтобы в первый раз в f1 вызвался метод предка. во всех остальных случаях будет вызван метод потомка. в Racket такое сделать неудасться -- там нет приведения типов в принципе. в CL тоже не удастся, несмотря на наличие множественного наследования

          Добавлено
          Цитата MyNameIsIgor @
          Цитата korvin @
          тем, что шаблон никак не может проверить, реализует ли переданный ему тип нужный интерфейс (методы foo и bar), потому и получаем ошибки уже после раскрытия шаблона в кучу кода.

          Компилятор просто скажет, что тип не реализует данный метод.
          Цитата korvin @
          или таки может?

          Можно.

          так он это скажет перед раскрытием шаблона или уже после, на раскрытом коде?
            Цитата korvin @
            я ж говорю, проверить не могу, но должен быть такой. а что тут странного? задача сводится всего лишь к перекрытию метода предка и приведению объекта-потомка к типу объекта предка, чтобы в первый раз в f1 вызвался метод предка. во всех остальных случаях будет вызван метод потомка.

            В том то и дело, что, например, в C# реализация интерфейса делает метод виртуальным. И впоследствии его переопределение в потомке приводит к тому, что даже при касте потомка в предка вызывается метод потомка, как и должно быть с виртуальными методами.

            Добавлено
            Цитата korvin @
            так он это скажет перед раскрытием шаблона или уже после, на раскрытом коде?

            Ээээ... А что такое "раскрытие шаблона"?
              Цитата D_KEY @
              Кто кого заменяет - это еще вопрос. Интерфейс явно вводит новый "тип" и требует, чтобы аргумент ему соответствовал. Не очень-то соответствует "утиной типизации" которая нам тут, фактически, нужна.
              Шаблон же говрит, что тип может быть любым, но требуется, что вот такие-то операции можно осуществить с объектами этого типа.

              дык некий набор операций -- это фактически и есть абстрактный тип данных =) другое дело, что возможно было бы удобней, чтобы интерфейсы не занимали пространство имен типов данных, однако множество пространств имен тоже не в каждом языке хорошо, вот в CL -- хорошо, а для топиковых языков, имхо, не очень
                Цитата korvin @
                я ж говорю, проверить не могу, но должен быть такой. а что тут странного? задача сводится всего лишь к перекрытию метода предка и приведению объекта-потомка к типу объекта предка, чтобы в первый раз в f1 вызвался метод предка. во всех остальных случаях будет вызван метод потомка.

                Кстати, а как тогда будет выглядеть код, если я захочу в B заменить реализую f из A, чтобы любой код, ожидающий A, использовал новую реализацию?
                  Цитата korvin @
                  Цитата D_KEY @
                  Так ты ответишь, чем тебе не нравится:
                  ExpandedWrap disabled
                    template<typename T>
                    void f(T x)
                    {
                        x.foo();
                        x.bar();
                    }

                  ?

                  тем, что шаблон никак не может проверить, реализует ли переданный ему тип нужный интерфейс (методы foo и bar)

                  Тебе будет сказано, что в таком-то шаблоне, параметаризированном таким-то типом, произошла ошибка, которая заключалось в том, что у объектов данного типа нет таких методов.
                  Простыни ошибок получаются тогда, когда слишком много шаблонов(компилятор описывает тебе полностью весь контекст возникшей ошибки). Концепты решают эту проблему, но их не будет в новом стандарте :'(
                    Цитата MyNameIsIgor @
                    В том то и дело, что, например, в C# реализация интерфейса делает метод виртуальным. И впоследствии его переопределение в потомке приводит к тому, что даже при касте потомка в предка вызывается метод потомка, как и должно быть с виртуальными методами.

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

                    Цитата MyNameIsIgor @
                    Ээээ... А что такое "раскрытие шаблона"?

                    инстанциирование

                    исходник шаблона:
                    ExpandedWrap disabled
                      template<typename T>
                      void f(T x)
                      {
                          x.foo();
                          x.bar();
                      }

                    инстанциирование:
                    ExpandedWrap disabled
                      f(<Type> var);

                    раскрывается в
                    ExpandedWrap disabled
                      // somewhere...
                      void f_123456(Type x)
                      {
                          x.foo();
                          x.bar();
                      }
                      ...
                       
                      f_123456(var)

                    т.е. при инстанциировании "где-то там" объявляется функция с уникальным именем и это имя уже подставляется в инстанциированном вызове. ну это грубо и м.б. уже не так все, раньше вроде примерно так шаблоны работали
                      Цитата korvin @
                      инстанциирование

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

                      Добавлено
                      Цитата korvin @
                      да, я в курсе, в делфи методы по-умолчанию не виртуальны, для этого есть ключевое слово virtual.

                      В шарпе так же, что не мешает описанному поведению.
                        Цитата MyNameIsIgor @
                        Кстати, а как тогда будет выглядеть код, если я захочу в B заменить реализую f из A, чтобы любой код, ожидающий A, использовал новую реализацию?

                        эм... не совсем понял. если ты в код, ожидающий А, передашь объект класса А, то будет вызван метод класса А. нельзя в потомке переопределить метод предка так, чтобы в инстансах предка он тоже поменялся. или ты имеешь в виду, что, при передаче В всегда вызывался метод В, даже если в А этот метод определен не как виртуальный? тогда не знаю, надо поэкспериментировать, я с этими virtual/override/overload давно не заморачивался, так что не помню что там да как
                          Цитата MyNameIsIgor @
                          Цитата korvin @
                          грубо говоря (точно проверить сейчас возможности нет) в Делфи это будет так:

                          Дык не то ведь! Функции должны принимать интерфейсы, об их конкретных реализациях они ничего не знают.
                          Ну, может, если так переделаю, станет понятнее
                          ExpandedWrap disabled
                            #include <iostream>
                             
                            class IA
                            {
                            public:
                              virtual void f() = 0;
                            };
                             
                            class IB : public IA
                            {
                            public:
                              virtual void g() = 0;
                            };
                             
                            class A : public IA
                            {
                            public:
                              virtual void f() { std::cout << "A::f()" << std::endl; }
                            };
                             
                            class Base : public IB
                            {
                              void f() { IB_f(); }
                            public:
                              virtual void IB_f() = 0;
                            };
                             
                            class B : public A, public Base
                            {
                            public:
                              virtual void g() { std::cout << "B::g()" << std::endl; }
                              virtual void IB_f() { std::cout << "B::f()" << std::endl; }
                            };
                             
                            void f1(IA& iface)
                            {
                              iface.f();
                            }
                             
                            void f2(IB& iface)
                            {
                              iface.f();
                              iface.g();
                            }
                             
                            int main()
                            {
                              B b;
                             
                              f1(static_cast<A&>(b));
                              f1(static_cast<IB&>(b));
                              f2(b);
                             
                              return 0;
                            }

                          ExpandedWrap disabled
                            A::f()
                            B::f()
                            B::f()
                            B::g()

                          ExpandedWrap disabled
                            type
                              IA = interface
                                procedure f;
                              end;
                             
                              IB = interface (IA)
                                procedure g;
                              end;
                             
                              A = class(TInterfacedObject, IA)
                                procedure f; virtual;
                              end;
                             
                              B = class (A, IB)
                                procedure f; override;
                                procedure g;
                              end;
                             
                             
                            procedure A.f;
                            begin
                              Writeln( 'A.f' );
                            end;
                             
                            procedure B.f;
                            begin
                              Writeln( 'B.f' );
                            end;
                             
                            procedure B.g;
                            begin
                              Writeln( 'B.g' );
                            end;
                             
                             
                            procedure f1 (const x : IA);
                            begin
                              x.f;
                            end;
                             
                            procedure f2 (const x : IB);
                            begin
                              x.f;
                              x.g;
                            end;
                             
                             
                            var
                              x : B;
                            begin
                              x := B.Create;
                              f1( x as A);
                              f1( x );
                              f2( x );
                            end;

                          ExpandedWrap disabled
                            B.f
                            B.f
                            B.f
                            B.g


                          Цитата MyNameIsIgor @
                          В том то и дело, что, например, в C# реализация интерфейса делает метод виртуальным. И впоследствии его переопределение в потомке приводит к тому, что даже при касте потомка в предка вызывается метод потомка, как и должно быть с виртуальными методами.

                          Замечательно, подведём итоги:
                          Delphi +
                          C# +
                          C++ -

                          Добавлено
                          Цитата MyNameIsIgor @
                          Цитата korvin @
                          а, пардон, static_cast умышленно был сделан; тоже не очень-то соотвествует ООП

                          Странное какое-то у вас представление о ООП...

                          Ну вы ещё в полиморфизме используйте static_cast и называйте нас ненормальными :lol:

                          Добавлено
                          Цитата MyNameIsIgor @
                          Кстати, а как тогда будет выглядеть код, если я захочу в B заменить реализую f из A, чтобы любой код, ожидающий A, использовал новую реализацию?

                          Если правильно понял, то также как и у меня.
                            Цитата korvin @
                            1) совпадают только имена, количество и типы параметров разные -- просто два перегруженных метода. ты ж с Java знаком?
                            2) совпадают полностью сигнатуры -- никакой колизии, просто один и тот же метод, в чем проблема? пересечение множеств всего-навсего
                            Ну, первое не проблема. А вот второе - категорическое нет. Это методы разных интерфейсов. С какого перепуга они окажутся одним и тем же? Имена совпали? Бывает. Кто виноват? Да никто. Интерфейс IHistory может иметь право иметь метод LifeTime()? А интерфейс ITCP? А как быть чатилке, которой понадобился компонент, реализующий оба? Знаешь, я предпочту ошибку компиляции, чем молчаливое слияние в один метод.
                            Нет разницы, множественно наследуются интерфейсы ли или их реализации. Случайные коллизии имён от этого не пропадут сами собой. Вон, Shaggy показал приятный сахарок, сделать который "имеющимися средствами", как показал Повстанець, несложно через промежуточную реализацию, переименовав конфликтующие методы. Зато Shaggy лишён возможности наследовать готовые реализации ITCP и IHistory, написанные с год назад для разных проектов. Вот объединить бы оба плюса в одни Плюсы...
                            Цитата korvin @
                            и без шансов где-то забыть поставить очередной virtual
                            Ну, забыть поставить можно и очередной override.
                            Цитата DesweR @
                            Delphi +
                            C# +
                            C++ -
                            DesweR, как обычно, ничего не понял, но вставил. Речь шла о том, что при передаче в функцию, ожидающую интерфейс A, и получая в ней поведение интерфейса B - это только в Delphi и C# считается за +. Интересно посмотреть на счастливого программера, меняющего время жизни TCP-пакета и получающего вместо этого смену длины истории диалога.
                            Цитата DesweR @
                            Ну вы ещё в полиморфизме используйте static_cast и называйте нас ненормальными
                            Я-таки вижу в Дельфийном коде AS? Или мне мерещится? ...Ах да, он же не работает, тьфу ты... работает как и должен работать в Дельфи, угу.
                            Если кто не понял. А то как слепые, такое ощущение. static_cast<> там играет роль селектора реализаций интерфейса A. Если уж горе-дизайнер надизайнил такую иерархию, что бедному Повстанцу теперь за ним разгребать, то выбор требуемой одной из двух копий реализации A выполняется одним чихом. "А у вас?" ©
                            Сообщение отредактировано: Qraizer -
                              Цитата Qraizer @
                              Цитата DesweR @
                              Delphi +
                              C# +
                              C++ -
                              DesweR, как обычно, ничего не понял, но вставил.

                              Да я вообще в осадок выпал... Вот что сказать человеку, утверждающему, что небо красное? :blink:
                              Цитата DesweR @
                              Ну вы ещё в полиморфизме используйте static_cast и называйте нас ненормальными

                              Привидение потомка к предку и предка к потомку - две большие разницы.
                              Цитата DesweR @
                              Если правильно понял, то также как и у меня.

                              Слава Богу, хоть что-то поняли... Только сначала я просил как раз иное поведение. И уже после того, как korvin привёл код, который по моим представления им не обладал (что вы и подтвердили), я спросил, как же тогда будет выглядеть код с переопределение метода класса A в B.
                                Цитата Qraizer @
                                Ну, первое не проблема. А вот второе - категорическое нет. Это методы разных интерфейсов. С какого перепуга они окажутся одним и тем же? Имена совпали? Бывает. Кто виноват? Да никто. Интерфейс IHistory может иметь право иметь метод LifeTime()? А интерфейс ITCP? А как быть чатилке, которой понадобился компонент, реализующий оба? Знаешь, я предпочту ошибку компиляции, чем молчаливое слияние в один метод.

                                это ООПшно, объект не может и не должен реагировать на одно и то же сообщение по-разному.

                                Добавлено
                                Цитата Qraizer @
                                Цитата korvin @
                                и без шансов где-то забыть поставить очередной virtual
                                Ну, забыть поставить можно и очередной override.

                                дык конечно, задолбали все эти лишние сущности

                                Добавлено
                                Цитата Qraizer @
                                DesweR, как обычно, ничего не понял, но вставил. Речь шла о том, что при передаче в функцию, ожидающую интерфейс A, и получая в ней поведение интерфейса B - это только в Delphi и C# считается за +.

                                это вообще-то везде так, кроме C++.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (495) « Первая ... 139 140 [141] 142 143 ...  494 495


                                Рейтинг@Mail.ru
                                [ Script execution time: 0.2541 ]   [ 15 queries used ]   [ Generated: 31.07.26, 04:05 GMT ]