Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.156] |
|
|
Правила раздела:
| Страницы: (495) « Первая ... 159 160 [161] 162 163 ... 494 495 ( Перейти к последнему сообщению ) |
Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
|
Сообщ.
#2401
,
|
|
|
|
Цитата korvin @ гарантирует. согласно логике работы объектов конкретного класса. не нравится -- опирайтесь на некоторый абстрактный класс File, только не надо потом ругаться, если кто-то в потомке переопределит метод Seek и он будет делать "не то, что Вам хотелось", а приведение потомка к предку испортит логику работы потомка Ну, так если согласно логики конкретного класса, то с какого перепугу она принимает интерфейс то? Зачем вообще такой ничего не гарантирующий интерфейс нужен? Добавлено Вообще, господа, я решительно устал. Спасибо за внимание, я кончел. |
|
Сообщ.
#2402
,
|
|
|
|
Цитата Qraizer @ D_KEY, я и молчал. Не из-за недостатка агрументов, а из-за отсутствия новых аргументов. Свои я высказал двумя прошлыми постами, только ты не захотел слушать. А сказано было ни более ни менее, чем "движения нет, сказал мудрец брадатый" и дальше ещё три строчки. Я в твоих постах именно относительно обсуждаемой проблемы не увидел аргументов, разве что голословные утверждения. Цитата Абстрактный класс... интерфейс... концепт... Жизнь, D_KEY, жизнь. Я ж просил попытаться выразить свои доводы не кодом, но документацией. Я ж кода не приводил почему, думаешь? Я не только кодом выражал, вначале были слова, которые оказались не поняты. Код - попытка объяснить не словами, а примером. Цитата Не в коде дело, а в нашедших в нём своё отражение идеях программера. И ещё - в человеческом факторе. Давай я не буду напоминать об интерфейсе операции / для целочисленных аргументов. И твоём желании считать по дефолту все методы константными, кроме явно указанных как наоборот. Тоже утопично, если подумать, и дело совсем не в обратной совместимости. Аргументированно. А может все-таки скажешь, почему утопично? Я, знаешь ли, люблю когда мои заблуждения развеивают. И не толко методы, но и поля, переменные и т.п. Расскажи, пожалуйста, какие ты видишь проблемы в этом случае? Добавлено Цитата MyNameIsIgor @ Вот через две страницы мы всего лишь пришли к пониманию того, что сигнатура и название - это ещё далеко не всё. Конечно, не все. Только это никак не влияет на то, что интерфейсу знать ничего больше не нужно. Цитата Цитата D_KEY @ То есть концепты можно выкинуть за ненадобностью? Ведь требуем мы именно этого... Заданное название и сигнатуру. Не только не выкидывать, но ещё и контракты добавить по соответствующему предложению в комитете. Так можешь пояснить, почему, если мы берем два концепта с одинаковым методом, то объект, удовлетворяющий обоим, у тебя опасения не вызывает, а в случае интерфейсов должен быть конфликт? Цитата Ну, вот, опять двадцать пять... А можно я ещё одну ересь скажу? Я вообще не вижу необходимости иметь в языке "интерфейсы". Меня вполне устроит множественное наследование. Это уже другой вопрос. В С++ нет интерфейсов. Вот и подумай, если бы решили вводить интерфейсы, то зачем и какими бы они были? Интерфейсы не наследуются. Они подобны концептам. Цитата А он - обычная тупая сконина, которая должна слушаться, а не палки в колёса вставлять своими альтернативными взглядами на жизнь с далеко идущими выводами. Мы говорим о новом для С++ языковом механизме(поскольку в С++ нет интерфейсов). Естественно, что программист будет решать когда и как его использовать. Ура, пошли аргументы! Цитата Потому первая крайне важная для моего ответа, известная всем вещь: использующий интерфейс код ничего не знает о его реализациях. Это крайне важное отличие, ибо шаблон знает в момент компиляции тот тип, который ему дают как реализующий нужный концепт. Но, как ты правильно говоришь, компилятор знает лишь нужные ему сигнатуры, об их семантике он не знает ничего. В случае интерфейсов ситуация абсолютно идентична. Цитата Второй важный момент: мы громогласно заявляем, что реализуем интерфейс, и в то же время скромненько в стороночке молчим о релизуемых нами концептах. Потому что не знаем мы в каких шаблонах будут использовать написанный нами класс. Вопросы соответствия класса концепту будем решать не мы, а тот, кто наш класс использует. Ему специально по такому праздничному случаю и маппинг дали. Не соглашусь. Ты, как автор обобщенного кода говоришь, что мне нужны объекты, вот с такими вот "свойствами". И описываешь все это безобразие в концепте. Но вместо концепта ты можешь описать интерфейс. Так в чем разница? Цитата А вот теперь давай подумаем, что нам надо, чтобы убедиться в соответствии типа концепту? Нам нужен механизм проверки. Почему был выбран именно механизм по названию метода и его сигнатуре? А потому что для иной проверки у компилятора нет информации. В отличие от интерфейсов, где автор реализации явно ему сказал, что реализовал. Я выше писал о том, что хотелось бы, чтобы компилятор мог сам увидеть, что класс полностью соответствует интерфейсу. (Создал бы под капотом proxy-объект). То есть было бы поведение, соответствующие шаблонам и концептам, но только в рантайме. Именно это было бы полезно в С++, поскольку "обычные" интерфейсы нам не нужны - бесполезны. Насколько я понял, именно так ведут себя интерфейсы в Go... Цитата Собственно, всю тему temlates vs generics это и перетирали. Это не очень связано с обсуждаемой проблемой. Цитата в случае концептов используется механизм проверки соответствия по имени метода и его сигнатуре потому, что нет альтернативы ввиду недостаточности информации о коцептах в точке использования класса у реализующего этот класс. Попытка ввести механизмы, предоставляющие подобную информацию, приведут к дискредитации шаблонов и утраты ими большей части своих возможностей. А я тебе еще раз поясню, что я говорю не об "интерфейсах", в принципе, заменяемых в С++ абстрактными классами. Цитата Кстати, если есть интерфейс, принимающая его функция и реализующий его класс ![]() ![]() interface IA { void f(); } void do_something_with_IA(IA ia) { /*какой-то код*/ } class A : IA { void f() { /*какой-то код*/ } } а так же существует код, использующий класс A (сующий его во всякую щель, ожидающую IA), но этому коду ещё известно и о ![]() ![]() interface IB { void f(); } void do_something_with_IB(IB ib) { /*какой-то код*/ } то можно ли запихнуть экземпляр A в do_something_with_IB? А что, по сигнатурам всё проходит! Да и с концептами так делать можно. И вообще у нас поведение по умолчанию - "сливать" "одинаковые" методы. Мой ответ - категорическое нет. Не реализовывал автор A интерфейс IB и всё тут. И нефиг за него додумывать. И какой смысл тогда таких интерфейсов в языках со множественным наследованием? Мое мнение, что если таким языкам и нужны интерфейсы(а мне кажется, что нужны), то это должен быть более гибкий механизм, похожий на концепты(а может слитый с ним воедино), только работающий в рантайме. Добавлено Цитата Adil @ Цитата korvin @ Реализовал интерфейс IB::f()? Да автор IA про него и не слышал и во сне не видел, и понятия не имеет, что должен делать IB::f(). Вот может наглядней так:как это не реализовал, когда реализовал? все методы соответствующих сигнатур на месте => реализовал ![]() ![]() interface IAL { int shift(int value); } void do_something_with_IA(IAL ia) { /*какой-то код*/ } class A : IAL { int shift(int value) { return value << 1; } } interface IBR { int shift(int value); } class B : IBR { int shift(int value) { return value >> 1; } } void do_something_with_IB(IBR ib) { /*какой-то код*/ } Я уже говорил, что аналогичная проблема в концептах и шаблонах никого не беспокоит Добавлено Цитата Adil @ Да, но вы то предлагаете, чтобы этого достигал не программист, а компилятор, выбирая shift одного интерфейса при множественном наследовании. Adil, тут нет вообще никакого наследования, ни одиночного, ни множественного. Добавлено Цитата MyNameIsIgor @ Вообще, господа, я решительно устал. Спасибо за внимание, я кончел. Ну вот... Я только думал вернуться к конструктивному обсуждению(да, я верю, что в данном случае, это возможно). |
|
Сообщ.
#2403
,
|
|
|
|
Цитата MyNameIsIgor @ Цитата D_KEY @ Ну вот... Я только думал вернуться к конструктивному обсуждению(да, я верю, что в данном случае, это возможно). Удалено модератором Хорошо, договорились |
|
Сообщ.
#2404
,
|
|
|
|
А это в общем-то и есть интерфейс. Ну да, там вместо завораживающего некоторых слова interface написано class.
|
|
Сообщ.
#2405
,
|
|
|
|
Цитата D_KEY @ То есть было бы поведение, соответствующие шаблонам и концептам, но только в рантайме. Именно это было бы полезно в С++, поскольку "обычные" интерфейсы нам не нужны - бесполезны. Насколько я понял, именно так ведут себя интерфейсы в Go... зачем в рантайме? вполне себе в компайл-тайме =) ведь компилятор обладает всей информацией о классе и интерфейсе, соответственно проверку соответствия класса интерфейсу можно проводить во время компиляции. не ну если хочется, то можно и в рантайме, но я бы не стал называть это интерфейсами, дабы не путаться, просто предикатная функция + немножко рефлексии: ![]() ![]() func implements (x : any, i : interface) { return implements( x.class(), i ) } func implements (c : class, i : interface) { for m in i.methods() { if not member( m, c.methods() ) { return false } } return true } Добавлено Цитата trainer @ А это в общем-то и есть интерфейс. Ну да, там вместо завораживающего некоторых слова interface написано class. нет, это класс: 1) у него есть реализация, которую ты не видишь; 2) можно инстанциировать экземпляры этого класса. |
|
Сообщ.
#2406
,
|
|
|
|
Цитата korvin @ Ну вот когда ты покажешь реализацию, тогда и можно будет сказать о его методах больше, чем я выше написал.у него есть реализация, которую ты не видишь Цитата korvin @ А я говорю - нельзя. Мое слово против твоего. Реализация не приведена - доказать нельзя.можно инстанциировать экземпляры этого класса ![]() ![]() #define class interface Добавлено P.S. А если у меня в C++ конструкторы класса закрыты и соответственно нельзя "инстанциировать экземпляры этого класса" - значит этот класс является интерфейсом? |
|
Сообщ.
#2407
,
|
|
|
|
Цитата korvin @ зачем в рантайме? вполне себе в компайл-тайме =) ведь компилятор обладает всей информацией о классе и интерфейсе, соответственно проверку соответствия класса интерфейсу можно проводить во время компиляции. Проверку осуществлять, конечно, нужно во время компиляции. Я имел в виду позднее связывание. Добавлено trainer, классы не интерфейсы. И классы от них не наследуют. Именно из-за непонимания этого и идут те разногласия, которые мы наблюдаем последние несколько страниц. И в С++ интерфейсов нет, хотя в том виде, в котором они реализованы в таких языках, как C#, Java и Delphi, они в С++ бесполезны. Добавлено И даже используя #define interface class, ты только введешь в заблуждение клиентов... |
|
Сообщ.
#2408
,
|
|
|
|
Цитата trainer @ Ну вот когда ты покажешь реализацию, тогда и можно будет сказать о его методах больше, чем я выше написал. зачем? реализация скрыта. инкапсуляция же Цитата trainer @ А я говорю - нельзя. Мое слово против твоего. Реализация не приведена - доказать нельзя. опять же, зачем тебе реализация? ![]() ![]() A a; вот тебе создали экземпляр |
|
Сообщ.
#2409
,
|
|
|
|
Цитата D_KEY @ Ну почему заблуждение. Отнюдь. Коммунизм вот тоже утопия, но разве это делает его идеи ошибочными? Считай это намёком.А может все-таки скажешь, почему утопично? Я, знаешь ли, люблю когда мои заблуждения развеивают. И не толко методы, но и поля, переменные и т.п. Расскажи, пожалуйста, какие ты видишь проблемы в этом случае? Если надоест искать причины. Потому что в C++ нет константных объектов, кроме литералов. Любое упоминание const не более чем обещание, которое теми или иными способами как-то там проверяется, и способы эти не дают абсолютных гарантий. Будь то проверка компилятора, которого при желании легко заткнуть кастом или альясным указателем, или атрибут секции памяти, выставленный ОС, не находящейся под контролем Стандарта языка, или физическое свойство участка памяти, неподконтрольное даже ОС. Зачем тогда лукавить? Поэтому и утопия. Язык такой философии, как у C++, не может себе позволить искажать истинное положение вещей. Вот его дефолтовое отсутствие нареканий не вызывает, ибо отражает реальные характеристики подавляющего большинства исполнительных платформ (а иные платформы, вообще говоря, для C++ просто неинтересны, там больше подойдёт какая-нибудь эзотерика). И если в отдельно взятом месте программист поставит-таки const, то это будет его обещание, а не языка, и язык так уж и быть сделает всё возможное, чтобы поддержать программиста. Чтобы гарантии действительно были, это либо должен был бы быть не C++, либо он должен опираться на железный фундамент в лице исполнительной платформы, что утопично ещё больше. ![]() ![]() struct IA { virtual void f() = 0; }; struct IB { virtual void f() = 0; }; struct X: IA, IB { void f() {} }; X x; |
|
Сообщ.
#2410
,
|
|
|
|
Цитата korvin @ А компилятор ответил 'Не могу создать экземпляр класса A - нет доступных конструкторов'. И? Значит это интерфейс?вот тебе создали экземпляр Цитата D_KEY @ Я понимаю, что если написано interface - то это завораживающая магия. классы не интерфейсы |
|
Сообщ.
#2411
,
|
|
|
|
Все-таки еще раз поясню свою позицию относительно интерфейсов.
В языках с множественным наследованием интерфейсы в духе C# и Java будут бесполезны, ибо практически всего того, ради чего они вводились, можно добиться через абстрактные классы и множественное наследование. Можно сказать даже, что интерфейсы в перечисленных выше языках является отчасти костылями, призванными решить те языковые проблемы, которые возникают в результате (нелогичного на мой взгляд) запрета на множественное наследование. Если в языках с множественным наследованием и нужны интерфейсы, то это должен быть более гибкий и полезный в хозяйстве механизм. На мой взгляд, ближе всего к такому понятию подходят концепты(в C++ и частично template constraints в D). Но все-таки отличия есть. Простой пример. ![]() ![]() concept A<typename T> { bool operator()(T &, const std::string &); }; template<typename T> where A<T> void f1(const T &obj) { //... if (obj("bla-bla-bla")) { //... } //... } concept B<typename T> { bool operator()(T &, const std::string &); }; template<typename T> where B<T> void g1(const T &obj) { //... if (!obj("bla-bla-bla")) { //... } //... } interface IA { bool operator()(/* IA& - нужно ли? ,*/ const std::string &); // ... }; void f2(IA &obj) { //... if (obj("bla-bla-bla")) { //... } //... } interface IB { bool operator()(/* IB& - нужно ли? ,*/ const std::string &); // ... }; void g2(IB &obj) { //... if (!obj("bla-bla-bla")) { //... } //... } //... class MyClass // Можем написать: // : public implement IA, // сообщаем, что реализуем интерфейс IA // public implement A // сообщаем, что реализуем концепт A // (получаем дополнительную проверку при компиляции) { public: bool operator()(const std::string &str) { //... } }; //... MyClass a; f1(a); // ok(класс удовлетворяет концепту A) g1(a); // ok(класс удовлетворяет концепту B) f2(a); // ok(класс удовлетворяет интерфейсу IA - м.б. лучше явный каст) g2(a); // ok(класс удовлетворяет интерфейсу IB - м.б. лучше явный каст) Конечно, такое поведение не всегда идеально, но никто не мешает разрешить разделить реализацию для разных интерфейсов, да и абстрактные классы никто не отменяет. В достаточно мощных языках, где тип является объектом первого рода, возможно соединение концептов и интерфейсов в один языковой механизм, т.к. в этом случае интерфейс может требовать все, что может требовать концепт, в том числе и внутренние типы. Хотя в общем случае возможности концептов все-таки шире. В С++ же эти механизмы объединить в любом случае нельзя, да и не нужно. Относительно пользы таких интерфейсов в С++... На практике это все решается обычными шаблонами и концептами(правда их не будет, что очень печально), хотя в случае динамики, приходится иногда вручную делать адаптеры, даже если сигнатуры и имена совпадают. Прошу прощение у Игоря, если он все-таки решил это прочитать и моя невменяемая простыня вызвала у него приступ тошноты... Добавлено Цитата Qraizer @ Цитата D_KEY @ Ну почему заблуждение. Отнюдь. Коммунизм вот тоже утопия, но разве это делает его идеи ошибочными? Считай это намёком.А может все-таки скажешь, почему утопично? Я, знаешь ли, люблю когда мои заблуждения развеивают. И не толко методы, но и поля, переменные и т.п. Расскажи, пожалуйста, какие ты видишь проблемы в этом случае? Если надоест искать причины. Потому что в C++ нет константных объектов, кроме литералов. Любое упоминание const не более чем обещание, которое теми или иными способами как-то там проверяется, и способы эти не дают абсолютных гарантий. Будь то проверка компилятора, которого при желании легко заткнуть кастом или альясным указателем, или атрибут секции памяти, выставленный ОС, не находящейся под контролем Стандарта языка, или физическое свойство участка памяти, неподконтрольное даже ОС. Зачем тогда лукавить? Поэтому и утопия. Язык такой философии, как у C++, не может себе позволить искажать истинное положение вещей. Вот его дефолтовое отсутствие нареканий не вызывает, ибо отражает реальные характеристики подавляющего большинства исполнительных платформ (а иные платформы, вообще говоря, для C++ просто неинтересны, там больше подойдёт какая-нибудь эзотерика). И если в отдельно взятом месте программист поставит-таки const, то это будет его обещание, а не языка, и язык так уж и быть сделает всё возможное, чтобы поддержать программиста. Чтобы гарантии действительно были, это либо должен был бы быть не C++, либо он должен опираться на железный фундамент в лице исполнительной платформы, что утопично ещё больше. Спасибо за разъяснения, твоя позиция ясна. Спорить тут не с чем, в том смысле, что ты в принципе прав... Цитата У меня тоже есть утопическое желание, чтобы код (лень выше искать, проще написать) ![]() ![]() struct IA { virtual void f() = 0; }; struct IB { virtual void f() = 0; }; struct X: IA, IB { void f() {} }; X x; Да, мне тоже кажется, что было бы лучше, если бы в С++ это не работало. Добавлено Цитата trainer @ Цитата D_KEY @ Я понимаю, что если написано interface - то это завораживающая магия.классы не интерфейсы Нет, дело не в ключевых словах |
|
Сообщ.
#2412
,
|
|
|
|
Цитата trainer @ А компилятор ответил 'Не могу создать экземпляр класса A - нет доступных конструкторов'. И? Значит это интерфейс? нет, это значит "нет доступных конструкторов" |
|
Сообщ.
#2413
,
|
|
|
|
товарищи С++-ники, вас самих не напрягает наличие кучи шаблонных типов указателей? то, что я насчитал:
smart_ptr auto_ptr shared_ptr weak_ptr unique_ptr scoped_ptr intrusive_ptr что-то наверняка упустил |
|
Сообщ.
#2414
,
|
|
|
|
Цитата korvin @ товарищи С++-ники, вас самих не напрягает наличие кучи шаблонных типов указателей? то, что я насчитал: smart_ptr auto_ptr shared_ptr weak_ptr unique_ptr scoped_ptr intrusive_ptr что-то наверняка упустил Это насчитал не ты, а Роб Пайк, что он и показывал на одной из презентации go. Кстати, поясни, где именно ты их насчитал и для чего каждый нужен ?Сразу скажу, что в стандарте их всего один. В новом стандарте он deprecated, но будут два других из этого списка. |
|
Сообщ.
#2415
,
|
|
|
|
Цитата D_KEY @ Это насчитал не ты, а Роб Пайк, что он и показывал на одной из презентации go. Кстати, поясни, где именно ты их насчитал и для чего каждый нужен ?Сразу скажу, что в стандарте их всего один. В новом стандарте он deprecated, но будут два других из этого списка. хы, значит у нас с ним мысли немного сходятся =)) я считал независимо, я просто перечисли то, что вспомнил по упоминаниям в инете, понятия не имею для чего каждый нужен (это и пугает) в стандарте может и один, но судя по интеу, пользуются многими в зависимости от ситуации |