На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (33) « Первая ... 4 5 [6] 7 8 ...  32 33  ( Перейти к последнему сообщению )  
> trait + impl vs class , навеяно Rust'ом
    :sarcasm: Англо-русский словарь не подойдёт?
      Цитата Qraizer @
      :sarcasm: Англо-русский словарь не подойдёт?

      А, понял откуда вы определения берёте. За сим закончим.
        Цитата MyNameIsIgor @
        ООП-интерфейсы не единственный способ (по крайней мере в плюсах) обеспечения динамической диспетчеризации.
        Эм. Короткий пример можно?
        Цитата DarkEld3r @
        Ну и в расте, как и в С++, мутабельность на уровне объектов, а не типов.
        В C++ мутабельности/иммутабельности как таковой нет, но есть константность, которой иногда можно заменить иммутабельность. Константость задается вполне себе на уровне типа. И можно создать шаблонную функцию принимающую как константный, так и мутабельный тип.
        Сообщение отредактировано: applegame -
          Цитата applegame @
          Короткий пример можно?

          Указатели на функции же.
            Цитата MyNameIsIgor @
            Указатели на функции же.
            А, точно. Часто встречается в сяшечных проектах. И часто как эмуляция тех самых ООП-интерфейсов :)
            Сообщение отредактировано: applegame -
              Цитата applegame @
              Функция принимающая любой тип, который неявно кастуется в строку:

              Неявно - никак. Но к типу можно предъявить требование наличия реализации трейта ToString.

              Цитата applegame @
              Ну и вторая задача: без оберток создать массив в который можно было бы засунуть объект любого типа неявно кастующегося в строку.

              Правильно я понимаю, что в этом "массиве" будут лежать типы разного размера? Тогда нет, нельзя, можно сложить только указатели на такие типы.

              Цитата applegame @
              В Rust нельзя 8-мибитное целое неявно скастовать к 16-битному?

              Неявно - нет.

              Цитата applegame @
              Или неявно скастовать наследника к предку?

              Наследование есть только для трейтов.

              Цитата D_KEY @
              Ну да, можно хранить в массиве.

              У трейтов "нет размер", вернее он неизвестен. Как их хранить в массиве? Можно хранить ссылки/указатели.

              Цитата D_KEY @
              Ну встроенные(несужающие) касты есть какие-то, да. Но свои сделать нельзя, если я правильно понимаю.

              Аналог reinterpret_cast тоже есть. Естественно, он объявлен как unsafe.

              А что значит "нельзя сделать свои касты"? Кто помешает, как и в С++ сделать функцию, например, my_super_cast? Можно и макрос.

              Добавлено
              Цитата D_KEY @
              Встроенные примитивные типы вроде приводятся(без потери точности).

              Нет, только через "as" (ключевое слово):
              ExpandedWrap disabled
                let e: i8 = 10;
                let ee: i32 = e; // error: mismatched types: expected `i32`, found `i8`
                let eee = e as i32; // OK.


              Добавлено
              Цитата applegame @
              Нечто подобное сделали, хоть и через жопу - BCCL

              В курсе, но я лучше подожду, пусть и С++17, а то и дальше, чем таким пользоваться. :)

              Цитата applegame @
              А трейты-потомки к трейтам-предкам тоже явно кастовать надо?

              Нет.

              Цитата applegame @
              ИМХО, классы типов в Хаскеле скорее похожи как раз на концепты.

              Почему?
                Цитата DarkEld3r @
                В курсе, но я лучше подожду, пусть и С++17, а то и дальше, чем таким пользоваться.

                А мне вот нравится как asio ругается в случае чего. Правда, там по-своему сделано, не BCCL.
                  Цитата DarkEld3r @
                  У трейтов "нет размер", вернее он неизвестен. Как их хранить в массиве? Можно хранить ссылки/указатели.
                  Пусть будут указатели, не суть.
                  Давайте попробуем выявить преимущества растовских трейтов перед D-шными интерфейсами/С++-ными абстрактными классами. Если таковые преимущества есть.

                  Задача:
                  Есть некий trait/интерфейс ToString описывающий функцию to_string без аргументов и возвращающую строку.
                  Есть два произвольных типа Foo и Bar, нужно описать трейт ToString для этих типов. Создать эти трейты, и засунуть их в массив:
                  Вариант на D. На C++ все аналогично:
                  ExpandedWrap disabled
                    import std.stdio;
                    import std.string;
                     
                    // это растовский trait
                    interface ToString {
                        string toString();
                    }
                     
                    // сторонний тип Foo
                    struct Foo {
                        int data;
                    }
                     
                    // сторонний тип Bar
                    struct Bar {
                        long data;
                    }
                     
                    // реализация traita ToString для стороннего типа Foo
                    auto makeToString(Foo foo) {
                        class Impl : ToString {
                            Foo payload;
                            override string toString() { return format("Foo(%s)", payload.data); }
                            // конструктор
                            this(Foo foo) { payload = foo; }
                        }
                        return new Impl(foo);
                    }
                     
                    // реализация traita ToString для стороннего типа Bar
                    auto makeToString(Bar bar) {
                        class Impl : ToString {
                            Bar payload;
                            override string toString() { return format("Bar(%s)", payload.data); }
                            // конструктор
                            this(Bar bar) { payload = bar; }
                        }
                        return new Impl(bar);
                    }
                     
                    void main() {
                        ToString[] arr;
                        auto bar = Bar(10);
                        auto foo = Foo(20);
                        arr ~= makeToString(bar);
                        arr ~= makeToString(foo);
                        foreach(o; arr) writeln(o.toString());
                    }
                    Цитата Qraizer @
                    Потому что без них, как и интерфейсов, вполне себе живётся на аналогах. Интерфейс – абстрактный класс, имеющий только чистые методы и не имеющий полей, который наследуется всегда виртуально. Трейты вообще не нуждаются в отдельном описании, любой шаблон предъявляет требования к свойствам своих аргументов посредством выполняемых над ними операций.

                    Стоп, не надо всё сразу. :)

                    С терминологией я более-менее согласен, хотя и с оговорками. На мой взгляд, в С++ интерфейсы вполне есть, в том смысле, что их можно изображать абстрактными классами. Да, можно сказать, что у "у тру интерфейсов" есть больше ограничений и т.д. Но это, имхо, будет так же интересно как спорить, что такое интерфейсы - концепты или "интерфейсы".

                    D-шные трейты вполне себе есть как отдельная сущность. И выглядят вполне удобно. А ведь они, по сути, как раз те же самые концепты, которые планируют появиться в С++. То есть с ними лучше, а значит "в отдельном описании" всё-таки нуждаются.

                    Про концепты и "отлично показали" я говорил именно в контексте языка D. Который, в рамках "мейнстрима" не так уж далеко ушёл от раста и остаётся таким же "экспериментом".

                    Добавлено
                    Цитата MyNameIsIgor @
                    Конечно неправильно. Потому что интерфейсы в C++ - это концепты. Что непонятного? :-?

                    Как будет угодно, такой спор мне не интересен. Я и дальше продолжу называть абстрактные классы интерфейсами и пока что меня отлично понимали. :)

                    Добавлено
                    Цитата applegame @
                    В C++ мутабельности/иммутабельности как таковой нет, но есть константность

                    В курсе, но я думаю, что мы друг друга поняли.

                    Цитата applegame @
                    И можно создать шаблонную функцию принимающую как константный, так и мутабельный тип.

                    А можно и не шаблонную. :)
                    ExpandedWrap disabled
                      void f(const int&);

                    Пожалуйста, передавать можно и константный и мутабельный тип.

                    А вот когда нам надо принимать разные типы и разные действия выполнять, то уже начинаются приседания. И нужно оно, чаще всего, тупо для std::forward. У раста семантика перемещения работает немного иначе, да и перегрузки функций нет. Ну то есть, если есть конкретная задача - можем обсудить и посмотрим получится ли реализовать, а не просто "а вот можно в расте вот этакий шаблон изобратьзить?".

                    Добавлено
                    Цитата MyNameIsIgor @
                    А мне вот нравится как asio ругается в случае чего. Правда, там по-своему сделано, не BCCL.

                    Ну если каждый будет свою реализацию велосипедить, то тоже не очень здорово. В общем, такие вещи лучше иметь в стандарте.
                      Цитата Qraizer @
                      Не понял. Задача написать метафункцию isConvertible<> на Плюсах? Я это делал, задолго до знакомства с бустом. И у Александреску есть.
                      Нет. Задачу я описал чуть выше и решил с помощью создания дополнительных классов-оберток.
                      Цитата DarkEld3r @
                      вот когда нам надо принимать разные типы и разные действия выполнять, то уже начинаются приседания.
                      Об этом я и говорю. Допустим у нас есть шаблонная функция принимающая ссылку и заполняющая ее объектом. Ссылка должна быть мутабельной. Вот немного притянутый за уши пример использования isMutable.
                      Сообщение отредактировано: applegame -
                        Цитата DarkEld3r @
                        Как будет угодно, такой спор мне не интересен

                        Сказал тот, кто сам предложил поспорить :facepalm: Ну, хорошо, не интересен так не интересен.
                        Цитата DarkEld3r @
                        Я и дальше продолжу называть абстрактные классы интерфейсами и пока что меня отлично понимали

                        Жаль, что вы общаетесь лишь с теми, чем тесный мирок ограничен симулоподными взглядами.

                        Созрел новый вопрос. Есть ли в Rust перегрузка обобщённых функций по трейтам?
                          Цитата applegame @
                          Пусть будут указатели, не суть.

                          Тогда никаких проблем:
                          ExpandedWrap disabled
                            struct MyToStringVec {
                                data: Vec<Box<ToString>>
                            }
                             
                            struct Test;
                             
                            fn main() {
                                let mut a = MyToStringVec { data: Vec::new() };
                                
                                a.data.push(Box::new(10));
                                a.data.push(Box::new("test"));
                                a.data.push(Box::new(Test)); // Error - Test не реализует ToString трейт
                            }


                          Цитата applegame @
                          Давайте попробуем выявить преимущества растовских трейтов перед D-шными интерфейсами/С++-ными абстрактными классами. Если таковые преимущества есть.

                          Можно добавлять существующим типам реализацию нужныx трейтов. Наверное, всё, но опять же - трейты нужны, чуть ли не в первую очередь, для дженериков.

                          Цитата applegame @
                          Есть некий trait/интерфейс ToString описывающий функцию to_string без аргументов и возвращающую строку.
                          Есть два произвольных типа Foo и Bar, нужно описать трейт ToString для этих типов. Создать эти трейты, и засунуть их в массив:

                          ExpandedWrap disabled
                            struct Foo {
                                data: i32,
                            }
                             
                            struct Bar {
                                data: i64,
                            }
                             
                            impl ToString for Foo {
                                fn to_string(&self) -> String {
                                    format!("foo({})", self.data)
                                }
                            }
                             
                            impl ToString for Bar {
                                fn to_string(&self) -> String {
                                    format!("bar({})", self.data)
                                }
                            }
                             
                            fn main() {
                                let mut arr = Vec::<Box<ToString>>::new();
                                arr.push(Box::new(Foo { data: 10 }));
                                arr.push(Box::new(Bar { data: 20 }));
                                
                                for val in arr {
                                    println!("{}", val.to_string());
                                }
                            }

                          Пожалуйста. Только я не пойму, что это должно доказать?

                          Добавлено
                          Цитата applegame @
                          Об этом я и говорю. Допустим у нас есть шаблонная функция принимающая ссылку и заполняющая ее объектом. Ссылка должна быть мутабельной. Вот немного притянутый за уши пример использования isMutable.

                          Тогда почему функция не может быть такой?
                          ExpandedWrap disabled
                            template <typename T>
                            void f(T&) {}


                          Цитата MyNameIsIgor @
                          Сказал тот, кто сам предложил поспорить :facepalm: Ну, хорошо, не интересен так не интересен.

                          Повторюсь - отвечал я другому человеку и на вполне конкретный комментарий. Как надо читать, чтобы начинать что-то доказывать про (пока ещё несуществующие, как языковый механизм) концепты я не знаю.

                          Цитата MyNameIsIgor @
                          Жаль, что вы общаетесь лишь с теми, чем тесный мирок ограничен симулоподными взглядами.

                          Ну спасибо, а то не знаю, что я бы без этой жалости делал. Действительно жаль, что я не начинаю рассказывать всё про все известные мне языки по любому поводу.

                          Цитата MyNameIsIgor @
                          Созрел новый вопрос. Есть ли в Rust перегрузка обобщённых функций по трейтам?

                          В смысле?
                          У разных трейтов могут быть одноимённые функции (ну а иначе было бы очень странно). Но перегрузки функций, в целом, нет. Так что и иметь две одноимённые функции, которые отличаются только типом аргумента-трейта нельзя.

                          Ну и специализации, в данный момент, тоже нет. Можно кидаться помидорами. :crazy: Впрочем, обсуждается и есть предложения. Очень надеюсь, что будет, иначе и впрямь убого получается.
                            Цитата DarkEld3r @
                            Пожалуйста. Только я не пойму, что это должно доказать?
                            Это доказало, что никакой особой разницы между растовскими traitами и ООП-интерфейсами нет. Холивор не имеет смысла.
                            Цитата DarkEld3r @
                            В смысле?
                            Наверное имеется в виду что-то типа:
                            ExpandedWrap disabled
                              void foo(T)(T data) if(isSerializable!T) {...}
                              void foo(T)(T data) if(isStringConvertible!T) {...}
                              Цитата applegame @
                              Это доказало, что никакой особой разницы между растовскими traitами и ООП-интерфейсами нет. Холивор не имеет смысла.

                              Хм... если мы именно про "ООП интерфейсы", то их снаружи обычно расширять нельзя. В смысле, добавлять добавлять существующему типу наследование от интерфейса.
                              Но я повторюсь про то, что трейты - они (ещё и) для дженериков.

                              Ну и примеры всё-таки не эквивалентные. В D порождается новый тип, который наследуется от интерфейса и содержит данные. В расте - нет.

                              Цитата applegame @
                              Наверное имеется в виду что-то типа:

                              Тогда нет, нет перегрузки. Но в данном случае, проблемы не вижу - просто для типа реализуем трейт сериализации (внутри можно использовать конвертацию в строку).
                              Сообщение отредактировано: DarkEld3r -
                                Цитата DarkEld3r @
                                Хм... если мы именно про "ООП интерфейсы", то их снаружи обычно расширять нельзя. В смысле, добавлять добавлять существующему типу наследование от интерфейса.
                                Ну я же добавил. Де-факто тоже самое, просто на слегка более низком уровне.
                                Цитата DarkEld3r @
                                В D порождается новый тип, который наследуется от интерфейса и содержит данные. В расте - нет.
                                Почему это нет? Твои реализации трейта ToString для Foo и Bar - это фактически порождение новых типов "унаследованных" от абстрактного трейта ToString и содержащих данные.
                                Сообщение отредактировано: applegame -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (33) « Первая ... 4 5 [6] 7 8 ...  32 33


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0595 ]   [ 15 queries used ]   [ Generated: 18.07.25, 15:14 GMT ]