Модераторы: Partizan, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Перегрузка функций как в Си++ или как в Джаве? 
V
    Опции темы
PashaPash
Дата 3.11.2008, 16:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 13
Всего: 49



Цитата(Dims @  3.11.2008,  14:30 Найти цитируемый пост)
Если они не видны извне, то их и нельзя переопределить. Мы же рассматриваем случай, когда метод А виден извне, используется одним из других методов Б и был переопределён в наследнике.

Утверждается, что это плохая ситуация, так как программист наследника не должен знать, что метод Б использует А. 

Я с этим не согласен. Если разработчик предка использовал метод А в методе Б и оставил метод А открытым, то он должен был написать в инструкции, что роль метода А сводится не только к тому, что он делает нечто, но она состоит ещё и в том, что он используется методом Б. Тогда программист наследника, прочтя инструкцию, узнает об этом и будет переопределять А с умом.

Если же это нежелательно, то метод А можно сделать оконечным и тогда никто его не сможет переопределить.

Проблема такого подхода - слишком много "может" на необходимых для успеха необходимых действиях. Это все на самом деле "может подумать о последствиях переопределения в наследнике, может написать документацию, может упомянуть в ней использование, может быть прочитает инструкцию, может быть будет думать при переопределении". Т.е. для нормального результата нужно много активных действий со стороны 2-х людей. В случае с невиртуальными по умолчанию "может" превращается в "должен". Должет обявить хотя бы protected, должен сделать виртуальной, должен прочитать warning при переопределении, должен написать new. Второй подход IMHO, безопаснее.
Цитата(Dims @  3.11.2008,  14:30 Найти цитируемый пост)
Не переводите вопрос в плоскость религиозных войн. Вы с одной стороны признаёте, что при создании Си-диез учитывался опыт Джавы, а с другой стороны пытаетесь принизить роль этого факта, говоря, что Си-диез это не Джава от МС.
Скажем, на обсуждаемый вопрос - особенности реализации наследования - больше влияния оказал C++ и COM, чем Java. 

Цитата(Dims @  3.11.2008,  14:30 Найти цитируемый пост)
На мой взгляд, связывание имеет отношение не к ООП, а к реализации. В моём гипотетическом языке компиллятор осуществлял бы раннее связываение при одном преобразовании типов и позднее -- при другом. 
А в реально существующем C# есть раннее связывание для невиртуальных методов, и позднее - для невиртуальных. И вроде никто (почти) не жалуется.


--------------------
PM MAIL WWW   Вверх
Dims
Дата 3.11.2008, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 0
Всего: 11



Цитата(PashaPash @  3.11.2008,  16:08 Найти цитируемый пост)
В случае с невиртуальными по умолчанию "может" превращается в "должен". 

От того, что человек напишет слово virtual, он не станет должен написать инструкцию. Он всё равно может проигнорировать эту обязанность.

C# требует, чтобы человек явно РАЗРЕШИЛ переопределять функции. А Джава требует, чтобы человек явно ЗАПРЕТИЛ переопределять функции, если это опасно.

В обоих случаях человек может наплевать на написание инструкции, которая в обоих случаях необходима.

Цитата(PashaPash @  3.11.2008,  16:08 Найти цитируемый пост)
Второй подход IMHO, безопаснее.

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

Я считаю, что это маловероятно. По крайней мере, ситуацию, при которой это так, ещё никто не придумал. 

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

Фактически, вот я пишу класс. Если я не объявил класс как sealed, значит, я предполагаю, что от класса будут производить наследников. И если при этом я не подписал все функции как virtual, то я исключил возможность нормального наследования от своего класса.

Иными словами, по умолчанию (то есть, без слов sealed и virtual) C# склоняет к созданию классов, непригодных к нормальному (с моей точки зрения) полиморфному наследованию. 

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

Отсюда и вопрос: когда это может пригодиться? То есть, когда может пригодиться именно затенение, а не переопределение. Ответа на этот вопрос до сих пор нами не найдено.

Цитата(PashaPash @  3.11.2008,  16:08 Найти цитируемый пост)
А в реально существующем C# есть раннее связывание для невиртуальных методов, и позднее - для невиртуальных.

Здесь явная опечатка. Когда что?

Цитата(PashaPash @  3.11.2008,  16:08 Найти цитируемый пост)
И вроде никто (почти) не жалуется. 

Ну, люди терпят даже такие хаотические языки, как PHP и Perl smile

PM MAIL   Вверх
PashaPash
Дата 3.11.2008, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 13
Всего: 49



Цитата(Dims @  3.11.2008,  16:44 Найти цитируемый пост)
Здесь явная опечатка. Когда что?

позднее - для виртуальных ес-но.

Цитата(Dims @  3.11.2008,  16:44 Найти цитируемый пост)
Только при условии, что мы предполагаем, что сплошь и рядом встречаются случаи, когда...

Я считаю, что это маловероятно. По крайней мере, ситуацию, при которой это так, ещё никто не придумал. 

Если ты не можешь увидеть такой ситуации, то значит ты пишешь код по принципу - "одна операция - один метод класса, который не вызывает остальные". 
Обычная ситуация. Есть метод А, он меняет внутренее состояние вызовом Б. Если методы виртуальные - значит ты готов поставить свою зарплату что кто-то другой всегда сможет корректно переопределить метод А и метод Б.

Цитата(Dims @  3.11.2008,  16:44 Найти цитируемый пост)
Фактически, вот я пишу класс. Если я не объявил класс как sealed, значит, я предполагаю, что от класса будут производить наследников. И если при этом я не подписал все функции как virtual, то я исключил возможность нормального наследования от своего класса.

Иными словами, по умолчанию (то есть, без слов sealed и virtual) C# склоняет к созданию классов, непригодных к нормальному (с моей точки зрения) полиморфному наследованию. 

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

Фактически, это значит что C# склоняет разработчиков ПОДУМАТЬ, перед тем как сделать метод частью public interface. Точно так же, как модификатор доступа private по умолчанию. Т.е. перед тем как позволить кому-то переопределить часть функционала, разработчик обязан обдумать последствия. Подумать что переопределяющий не будет иметь о внутреннем строении твоего класса вообще никакой информации. Ты не видишь негативных последствий - значит код за тобой никогда не дописывали нубы. Я пытался объяснить, что минимизация интерфейса по умолчанию - есть хорошо. Просто рассматривай виртуальные функции с той же стороны, что и как public. Если ты разрешил вызвать функцию - то кто-то ее вызовет. Если ты разрешил ее переопределить - то кто-то ее переопределит, причем совершенно не так, как ты этого ожидал. 
Ты сейчас отстаиваешь точку зрения которая полностью аналогична "а давайте сделаем public методы по умолчанию". Просто до этого писал на языке, где по умолчанию publiс, и теперь private с твоей точки зрения - ненормальная вещь. Просто пойми, что protected virtual это более широкий досуп к классу, чем public.

А "неполиморфным наследованием" - возможностью затенения. Оно используется в исключительных случаях (читай - никогда).
Цитата(Dims @  3.11.2008,  16:44 Найти цитируемый пост)
Ну, люди терпят даже такие хаотические языки, как PHP и Perl smile

Некоторые сидят на JavaScript, с только public методами. И потом им private делает невозможной нормальную (с их точки зрения) работу с объектами smile


--------------------
PM MAIL WWW   Вверх
Dims
Дата 3.11.2008, 19:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 0
Всего: 11



Цитата(PashaPash @  3.11.2008,  17:15 Найти цитируемый пост)
Если ты не можешь увидеть такой ситуации,

Если ты можешь, то опиши её пжлст прямо здесь.

Цитата(PashaPash @  3.11.2008,  17:15 Найти цитируемый пост)
Если методы виртуальные - значит ты готов поставить свою зарплату что кто-то другой всегда сможет корректно переопределить метод А и метод Б.

К чему этот пафос?

Цитата(PashaPash @  3.11.2008,  17:15 Найти цитируемый пост)
Фактически, это значит что C# склоняет разработчиков ПОДУМАТЬ

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

Если я умалчиваю sealed и умалчиваю virtual -- что я получаю? Класс, в котором при наследоваии методы можно только затенять. То есть, это наиболее распространённая ситуация с точки зрения разработчиков. Ну так опиши же, наконец, для чего она может быть нужна?

Повторяю, это должна быть не какая-то ОДНА ИЗ ситуаций, а САМАЯ распространённая, так как она получается в результате умолчания.

Цитата(PashaPash @  3.11.2008,  17:15 Найти цитируемый пост)
Точно так же, как модификатор доступа private по умолчанию. 

Вовсе не так же. private по умолчанию, потому что большую часть времени программист проводит в написании внутренней кухни класса. Поэтому private по умолчанию. Это разумно.

А зачем по умолчанию non-virtual? Кому нужны кучи классов, в которых нельзя переопределять методы?

Цитата(PashaPash @  3.11.2008,  17:15 Найти цитируемый пост)
Просто рассматривай виртуальные функции с той же стороны, что и как public. Если ты разрешил вызвать функцию - то кто-то ее вызовет. Если ты разрешил ее переопределить - то кто-то ее переопределит, причем совершенно не так, как ты этого ожидал.

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

Я, конечно, не отрицаю, что в каких-то случаях злонамеренное или дурное переопределение функций может привести к нарушению работы. Но КАК ПРАВИЛО это не так. И ты это косвенно подтверждаешь тем, что не можешь привести примера, в котором переопределение виртуальной функции вредно.

Цитата(PashaPash @  3.11.2008,  17:15 Найти цитируемый пост)
Ты сейчас отстаиваешь точку зрения которая полностью аналогична "а давайте сделаем public методы по умолчанию". 

Это тебе только так кажется.

Цитата(PashaPash @  3.11.2008,  17:15 Найти цитируемый пост)
Некоторые сидят на JavaScript, с только public методами. И потом им private делает невозможной нормальную (с их точки зрения) работу с объектами 

Ну вот я мог бы объяснить таким людям, зачем нужен private, потому что у меня есть практика их использования. А ты можешь ли объяснить мне, зачем нужно virtual/nonvirtual?
PM MAIL   Вверх
PashaPash
Дата 3.11.2008, 20:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 13
Всего: 49



Цитата(Dims @  3.11.2008,  19:03 Найти цитируемый пост)

К чему этот пафос?

Это не пафос, это суровая правда :(
Цитата(Dims @  3.11.2008,  19:03 Найти цитируемый пост)
Если я умалчиваю sealed и умалчиваю virtual -- что я получаю? Класс, в котором при наследоваии методы можно только затенять. То есть, это наиболее распространённая ситуация с точки зрения разработчиков. Ну так опиши же, наконец, для чего она может быть нужна?

Повторяю, это должна быть не какая-то ОДНА ИЗ ситуаций, а САМАЯ распространённая, так как она получается в результате умолчания.

Нет, ты получаешь класс в котором методы нельзя подменять без использования затенения. Это не значит что можно затенять методы без очень-очень веской причины. Пролистай стандартные классы .NET - в них очень неплохо продуман интерфейс и при этом - полно невиртуальных функций. Скажем, тот же BackgroundWorker - у него из виртуальных - только вызывающие события. Сравни его со своим воркером из соседнего топика. И сразу вылезет вот такой баг: 
Цитата(Dims @  27.10.2008,  22:25 Найти цитируемый пост)
По моим представлениям, наследник должен имплементить SpecificWork и (необязательно) Done. Внутри SpecificWork нужно проверять ShouldStop.get на предмет не пора ли завершиться.

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

Цитата(Dims @  3.11.2008,  19:03 Найти цитируемый пост)
В таком случае виртуальные функции надо вообще запретить. Ведь так получается по твоей логике.

Я, конечно, не отрицаю, что в каких-то случаях злонамеренное или дурное переопределение функций может привести к нарушению работы. Но КАК ПРАВИЛО это не так. И ты это косвенно подтверждаешь тем, что не можешь привести примера, в котором переопределение виртуальной функции вредно.

Не запретить, а сделать невиртуальными по умолчанию. А пример - да вот, прямо в твоем коде smile Ну или, навскидку, любой метод типа 
EnsureDataBound/EnsureChildControls который нужно вызывать из наследников, но ни в коем случае нельзя разрешить переопределить. Вообще, открой msdn, любой класс .net. Любая невиртуальная функция - пример. Если над ней подумать - то будут веские причины для ее невиртуальности.

Цитата(Dims @  3.11.2008,  19:03 Найти цитируемый пост)
Вовсе не так же. private по умолчанию, потому что большую часть времени программист проводит в написании внутренней кухни класса. Поэтому private по умолчанию. Это разумно.

Кухня класса - это не только private методы. Это еще и детали реализации для public/protected. Вопрос точно такой же - уменьшение связности и увеличение инкапсуляции. Для этих двух вещей и private и non-virtual - одно и то же.

Цитата(Dims @  3.11.2008,  19:03 Найти цитируемый пост)
Ну вот я мог бы объяснить таким людям, зачем нужен private, потому что у меня есть практика их использования. А ты можешь ли объяснить мне, зачем нужно virtual/nonvirtual? 

Ок, давай, попробуй объяснить мне, зачем нужен private. Делаем все public. Мои аргументы: Если что - всегда можно прочитать про конкретный метод в документации. Я писал на JavaScript, там все public, все счастливы. Пришел в вашу Java, тут все private по умолчанию. Приведи мне пример, когда public вреден. Что у вас вообще за OOP такое, если нельзя подменить любой кусок имплементации? Какое-то ненастоящее. И на все аргументы - типа инкапсуляция, кухня класса, связность, минимизация интерфейса, скрытие деталей реализации - я буду отвечать "а вот в JavaScript все public, и ничего, очень удобно, и инкапсуляция не нарушаешься. Если что - всегда можно в документации написать.".


--------------------
PM MAIL WWW   Вверх
diadiavova
Дата 3.11.2008, 20:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Так разговор об умолчаниях что ли? Я то думал, что вопрос в том, зачем делать метод невиртуальным. А оказывается это вообще не вызывает вопросов, вопрос в том, почему они не виртуальны по-умолчанию.
А так ли это важно вообще? На мой взгляд это разумно, просто потому, что методы могут быть такой же внутренней кухней как private-члены(независимо от видимости), только их ещё можно предоставить в к использованию вне кухни, не мешая работе кухни. Вот и всё.

Разработчики явы учли опыт, имевшийся в С++, а разработчики дотнета учли и опыт явы тоже. Результат мы видим.

ЗЫ

И в javascript есть private члены.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
diadiavova
Дата 3.11.2008, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Да, и ещё.
Я тут в связи с тем, что говорим на эту тему долго, заинтересовался одним вопросом. Попробовал я поискать хоть какую-то возможность вызвать из производного класса, в котором переопределён метод, первоначальную версию этого метода. Прибегал к разным ухищрениям, но такого способа я не нашёл. Не думаю, что это хорошо во всех случаях.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Dims
Дата 3.11.2008, 21:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 0
Всего: 11



Цитата(PashaPash @  3.11.2008,  20:29 Найти цитируемый пост)
Нет, ты получаешь класс в котором методы нельзя подменять без использования затенения.

Так зачем же подменять методы с использованием затенения?

Цитата(PashaPash @  3.11.2008,  20:29 Найти цитируемый пост)
И сразу вылезет вот такой баг

Где же тут баг?

Цитата(PashaPash @  3.11.2008,  20:29 Найти цитируемый пост)
У тебя в мелком классе всего пару виртуальных функций и уже есть родитель предьявляет требования к особенностям реализации наследника.

Класс всегда предъявляет требования к тем, кто им пользуется, в частности -- к наследникам.

Цитата(PashaPash @  3.11.2008,  20:29 Найти цитируемый пост)
Вот это - увеличение связности - и есть проблема виртуальных функций и наследования вообще. 

Ну наконец-то ты признался: в Си-диезе намеренно ограничено наследование, так как у наследования есть проблемы. smile

Цитата(PashaPash @  3.11.2008,  20:29 Найти цитируемый пост)
А пример - да вот, прямо в твоем коде

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

Цитата(PashaPash @  3.11.2008,  20:29 Найти цитируемый пост)
Ну или, навскидку, любой метод типа 
EnsureDataBound/EnsureChildControls который нужно вызывать из наследников, но ни в коем случае нельзя разрешить переопределить.

Это плохой пример, потому что он -- частный. Если в каком-то редком случае метод нельзя переопределять, то это можно запретить отдельным ключевым словом. А по умолчанию переопределение должно быть разрешено.

Цитата(PashaPash @  3.11.2008,  20:29 Найти цитируемый пост)
Если над ней подумать - то будут веские причины для ее невиртуальности.

Ну так подумай и выскажи свои соображения. 

Цитата(PashaPash @  3.11.2008,  20:29 Найти цитируемый пост)
Ок, давай, попробуй объяснить мне, зачем нужен private.

Так ты что, не знаешь?

Ещё раз. Я могу объяснить, зачем нужен private тем, кто им не пользовался, не привык и не знает, зачем он нужен. Потому что я пользовался, привык и знаю. 

Но, естественно, я не могу объяснить это тому, кто это и так знает, но собирается изображать, что не знает (ты) smile Потому что этот человек всё равно будет изображать, что "не понял", при любых объяснениях.

А с virtual -- другая ситуция. Я пришёл с Джавы и там никогда не пользовался затенением, не привык к этому и действительно не знаю, зачем оно нужно. Своими представлениями по опыту Си++ я уже поделился, и они мне кажутся неприменимыми в данном случае. А ты, вместо того, чтобы объяснить, или признаться, что сам не знаешь, просто аргументируешь на уровне раз большие дяди так сделали, значит это надо.

Цитата(PashaPash @  3.11.2008,  20:29 Найти цитируемый пост)
Приведи мне пример, когда public вреден.

Я про вред ничего не говорил. Я говорил про наиболее часто нужные вещи в работе.

Добавлено через 7 минут и 17 секунд
Цитата(diadiavova @  3.11.2008,  20:54 Найти цитируемый пост)
Так разговор об умолчаниях что ли? Я то думал, что вопрос в том, зачем делать метод невиртуальным.

Так это связано. Сперва (как я понял) аргументация была такая, мол, а почему бы и нет? Лозунг -- больше возможностей, плохих и хороших. Тогда я заметил, что невиртуальность сделана по умолчанию, то есть, трактуется не просто как одна из возможностей, а как важнейшая из них. 

Ведь если бы дело было только в том, чтобы предоставить ВОЗМОЖНОСТЬ делать невиртуальные функции, то можно было бы ввести слово "nonvirtual" и всё. А по умолчанию делать бы функции виртуальными.

Цитата(diadiavova @  3.11.2008,  20:54 Найти цитируемый пост)
только их ещё можно предоставить в к использованию вне кухни, не мешая работе кухни. 

Ну так как же можно помешать работе кухни с помощью виртуального метода?

Я определяю класс и в нём создаю метод, который делает бред. Ну всё -- значит я создал дурацкий класс. Объекты этого класса будут дурацкими вне зависимости от того, переопределил ли я виртуальную функцию или просто с нуля написал функцию, которая бредит.

Никаких проблем со связностью я тут не вижу. Никто ни с кем не связан. Есть просто сами по себе дурацкие объекты, и всё.

Добавлено через 8 минут и 18 секунд
Цитата(diadiavova @  3.11.2008,  21:16 Найти цитируемый пост)
Прибегал к разным ухищрениям, но такого способа я не нашёл. 

Как это нельзя? А как же ключевое слово base? (Оно же super в Джаве).
PM MAIL   Вверх
diadiavova
Дата 3.11.2008, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Цитата(Dims @  3.11.2008,  21:23 Найти цитируемый пост)
Как это нельзя? А как же ключевое слово base? (Оно же super в Джаве). 

Хорошее слово. Жаль только за пределами класса использовать нельзя.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Dims
Дата 3.11.2008, 21:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 0
Всего: 11



Вот код:

Код

class Program
    {
        static void Main(string[] args)
        {
            Производный п = new Производный();


            п.Звальщик();

            Console.ReadLine();
        }
    }

    class Базовый
    {
        public void Невиртуальная()
        {
            Console.WriteLine("Я невиртуальная в базовом классе");
        }

        public virtual void Виртуальная()
        {
            Console.WriteLine("Я виртуальная в базовом классе");
        }
    }

    class Производный : Базовый
    {
        public new void Невиртуальная()
        {
            Console.WriteLine("Я невиртуальная в наследнике");
        }

        public override void Виртуальная()
        {
            Console.WriteLine("Я виртуальная в наследнике");
        }

        public void Звальщик()
        {
            Невиртуальная();
            Виртуальная();
            base.Невиртуальная();
            base.Виртуальная();
        }
    }


вот вывод:

Я невиртуальная в наследнике
Я виртуальная в наследнике
Я невиртуальная в базовом классе
Я виртуальная в базовом классе

Добавлено через 2 минуты и 40 секунд
Вот такой код с теми же классами

Код

static void Main(string[] args)
        {
            Производный п = new Производный();

            ((Базовый)п).Невиртуальная();
            ((Базовый)п).Виртуальная();

            Console.ReadLine();
        }


даёт вот такой вывод:

Я невиртуальная в базовом классе
Я виртуальная в наследнике

Добавлено через 4 минуты и 10 секунд
То есть, чтобы вызвать невиртуальную функцию базового класса, нужно просто преобразовать тип.

А виртуальную функцию базового класса вызвать нельзя, в этом и состоит защита: функция, написанная, когда производного класса ещё не было в природе, не имеет права с ним работать, если была переопределена.
PM MAIL   Вверх
diadiavova
Дата 3.11.2008, 21:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Цитата(Dims @  3.11.2008,  21:23 Найти цитируемый пост)
Ну так как же можно помешать работе кухни с помощью виртуального метода?

Та я ж писал об этом. Когда на кухне используется метод, от него ожидается, что он будет делать дело определённым образом, а когда его переопределяют, он может делать это и по-другому. Это приходится учитывать. Не всегда возможно, да и лишний код, затраты на проверку условий и т. д. Я создаю метод для каких-то внутренних целей а кто-то его переопределяет, он работает не так как я задумал. И что в результате должно получиться? А человек, занимающийся наследованием моего класса не будет понимать откуда проблемы. У него ведь не обязательно должны быть исходные коды. 
Поэтому и по-умолчанию. А наследование это не только переопределение методов, а вообще расширение функциональности класса, определение новых методов например. Поэтому я не понимаю, к чему разговоры о нормальном наследовании и ненормальном.

Добавлено через 3 минуты и 33 секунды
Цитата(Dims @  3.11.2008,  21:38 Найти цитируемый пост)
А виртуальную функцию базового класса вызвать нельзя, в этом и состоит защита: функция, написанная, когда производного класса ещё не было в природе, не имеет права с ним работать, если была переопределена. 

Правильно, а если надо иметь такую возможность, то она есть - не делать метод виртуальным. Так что же: лучше бы её не было что ли?


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Dims
Дата 3.11.2008, 21:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 0
Всего: 11



Цитата(diadiavova @  3.11.2008,  21:50 Найти цитируемый пост)
Я создаю метод для каких-то внутренних целей а кто-то его переопределяет, он работает не так как я задумал. 

Во-первых, внутренний метод будет private.

А во-вторых, ну и что? Вред от этого будет только тому классу, который создан этим кем-то. И этот вред будет равен вреду от просто неправильно написанной функции. 

Но мы же не может надеяться запретить людям писать неправильные функции!

Добавлено через 3 минуты и 56 секунд
Цитата(diadiavova @  3.11.2008,  21:50 Найти цитируемый пост)
Правильно, а если надо иметь такую возможность, то она есть - не делать метод виртуальным. Так что же: лучше бы её не было что ли? 

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

Поэтому, её надо понять, не так ли?

Это сообщение отредактировал(а) Dims - 3.11.2008, 21:56
PM MAIL   Вверх
diadiavova
Дата 3.11.2008, 22:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Да, и кстати: затенение не является такой уж важной фичей. Это просто дополнительная возможность, своего рода компенсация того, что невиртуальные методы нельзя переопределить. Я уже писал, что затеняющий метод - это скорее перегрузка метода базового класса. На практике он почти не используется(поэтому и пример из практики привести трудно), но если это надо - то такая возможность есть.

Добавлено через 3 минуты и 4 секунды
Цитата(Dims @  3.11.2008,  21:55 Найти цитируемый пост)
Во-первых, внутренний метод будет private.

А во-вторых, ну и что? Вред от этого будет только тому классу, который создан этим кем-то. И этот вред будет равен вреду от просто неправильно написанной функции. 

Но мы же не может надеяться запретить людям писать неправильные функции!

Да, но при этом он не будет знать в чём ошибка, так что лучше запретить.
Цитата(Dims @  3.11.2008,  21:55 Найти цитируемый пост)
Так я ж говорю, что если бы это была просто возможность, которая когда-то (непонятно, когда) может пригодиться, то тогда ладно. Но это не просто возможность, а возможность по умолчанию. То есть, важная возможность.

Поэтому, её надо понять, не так ли?

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


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Dims
Дата 3.11.2008, 22:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 0
Всего: 11



Цитата(diadiavova @  3.11.2008,  22:02 Найти цитируемый пост)
Да, и кстати: затенение не является такой уж важной фичей.

Тогда почему она включается по умолчанию?

Цитата(diadiavova @  3.11.2008,  22:02 Найти цитируемый пост)
Да, но при этом он не будет знать в чём ошибка, так что лучше запретить.

Я не понимаю. Из этого следует, что нужно вообще запретить виртуальные функции. Но Вы же не делаете такой вывод?

Вы почему-то делаете вывод, что надо ПО УМОЛЧАНИЮ отключить. Но для такого вывода недостаточно одной лишь констатации вреда, нужно СРАВНИТЬ частоту вреда и пользы, и сделать по умолчанию то, что приносит больше пользы и меньше вреда.

Добавлено через 4 минуты и 14 секунд
Вот, например, вред от невиртуальной функции -- можно вызвать базовую функцию по отношению к производному классу. 

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

Кстати.

Я тут покопался, и прихожу к выводу, что это и есть основной мотив. Микрософт, как коммерческий разработчик, заинтересован в том, чтобы его классы можно было использовать только так, как он предусмотрел. То есть, получать только то, за что заплачено. Если есть какая-то возможность развития класса, которую Микрософт не заметил и, стало быть, не взял за неё деньги при продаже, то эта возможность должна быть ограничена.
PM MAIL   Вверх
diadiavova
Дата 3.11.2008, 22:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Цитата(Dims @  3.11.2008,  22:13 Найти цитируемый пост)
Тогда почему она включается по умолчанию?

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

Цитата(Dims @  3.11.2008,  22:13 Найти цитируемый пост)
Я не понимаю. Из этого следует, что нужно вообще запретить виртуальные функции. Но Вы же не делаете такой вывод?

А такой вывод я не делаю по двум причинам:
1.Знаю для чего нужны виртуальные методы.
2.Я уже миновал тот возраст, которому свойственен максимализм. Поэтому придерживаюсь средней линии. Вместо "всё или ничего" я предпочитаю "всё хорошо в меру и ко времени"

Цитата(Dims @  3.11.2008,  22:13 Найти цитируемый пост)
нужно СРАВНИТЬ частоту вреда и пользы

Я так понимаю, что возможность вреда уже не оспаривается. 
О частоте вообще можно спорить долго, честно говоря не представляю себе как эту самую частоту вообще можно исчислить. Если речь идёт о неопытном программисте, то ему вообще запретить надо почти всё, а супердуперпрофи может не париться, у него и так всё получится. 
Я тут недавно одному парню советы давал по прорисовке в форме, так он в таком удивлении был, когда я объяснил ему, что надо вызвать Invalidate при изменении параметров прорисовки. Ему и в голову не пришло, что методы бывают виртуальными, и что метод определённый в базовом классе может вызывать прорисовку, которую он сам настряпал.

Добавлено через 5 минут и 33 секунды
Цитата(Dims @  3.11.2008,  22:13 Найти цитируемый пост)
Вот, например, вред от невиртуальной функции -- можно вызвать базовую функцию по отношению к производному классу. 

А можно и не вызвать, а вслучае с виртуальной - выбора нет. Иногда это хорошо, а иногда - плохо.
Цитата(Dims @  3.11.2008,  22:13 Найти цитируемый пост)
Вот ещё вред от невиртуальной функции -- невозможно вмешаться переопределить то, чего не предусмотрел или забыл предусмотреть разработчик базового класса.

Если разработчик создал плохой класс(по забывчивости), не лучше ли использовать другие разработки(кто его знает, что он там ещё забыл)

Цитата(Dims @  3.11.2008,  22:13 Найти цитируемый пост)
Я тут покопался, и прихожу к выводу, что это и есть основной мотив. Микрософт, как коммерческий разработчик, заинтересован в том, чтобы его классы можно было использовать только так, как он предусмотрел. То есть, получать только то, за что заплачено. Если есть какая-то возможность развития класса, которую Микрософт не заметил и, стало быть, не взял за неё деньги при продаже, то эта возможность должна быть ограничена. 

Коммерческий разработчик - не только майкрософт, а возможность такая есть не только у встроенных классов.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.1449 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.