Явное преобразование типов
Если я правильно понял постановку вопроса, то просто имеется в виду, что
class Context : public IContext, public IExplorer
...и больше ничего. C# тут не при чем :-
да, правильно. Но откуда пользователь может узнать, что функция CreateContext на самом деле возвращает Context, а не IContext как следует из ее определения.
просто два "специалиста" в ООП пытались меня убедить, что это обычная практика:"Теория это одно, а на практике так делают". Еще упомянули COM......
Скажем так: достаточно часто встречающаяся.
Фактически - это динамическая типизация в действии.
Взять тот же паттерн "абстрактная фабрика" - такая фабрика никаким образом не сможет вернуть реальный тип объекта.
Или, например, есть множество объектов с опциональными дополнительными возможностями, тогда методы опять же будут принимать/возвращать базовый тип, и уже внутри каждого метода можно проверить поддерживает объект дополнительные возможности или нет.
> Скажем так: достаточно часто встречающаяся.
Это все потому, что на С++ никто программировать не умеет. Ибо досконально разобраться в нем практически невозможно. На самом деле это просто плохой стиль.
> Фактически - это динамическая типизация в действии.
Фактически - это просто плохой стиль. Либо надо объявлять правильный тип возвращаемого значения, либо RTTI.
> Взять тот же паттерн "абстрактная фабрика" - такая фабрика никаким образом не сможет
> вернуть реальный тип объекта.
А зачем нужен реальный тип объекта? Кажется это редко встречается, а когда встречается - то скорее всего это ошибка проектирования.
> Или, например, есть множество объектов с опциональными дополнительными
> возможностями, тогда методы опять же будут принимать/возвращать базовый тип, и уже
> внутри каждого метода можно проверить поддерживает объект дополнительные
> возможности или нет.
Опять-таки - скорее всего ошибка проектирования.
С уважением, Кучумов Андрей
>Ибо досконально разобраться в нем практически невозможно.
и как прикажете после этого относиться к этому:
>На самом деле это просто плохой стиль.
?
p.s. стиль как стиль
>> Ибо досконально разобраться в нем практически невозможно.
> и как прикажете после этого относиться к этому:
>> На самом деле это просто плохой стиль.
>?
Ну мы должны стремиться Ибо я же не сказал, что вообще невозможно.
Кроме того такие примеры разобраны во всех учебниках. А то, что лень набирать большее количество кода, так это конечно всем понятно.
> p.s. стиль как стиль
Как-то мне не попадался код в котором это было действительно нужно.
А так - все от требований к программе зависит. Если завтра надо работу сдать - то там и не такое напишешь. А если нужно, чтоб работало через 10 лет, сопровождаемое другими людьми -тогда и подумать не грех
С уважением, Кучумов Андрей.
Специалистов таких расстреливать надо.
> Опять-таки - скорее всего ошибка проектирования.
Вместо "громких" слов какие-нибудь факты и примеры будут?
> А зачем нужен реальный тип объекта? Кажется это редко встречается, а когда встречается - то скорее всего это ошибка проектирования.
Покажи, пожалуйста, пальцем где говорилось про реальный тип объекта?
Везде говорилось, что методы возвращают/принимают интерфейс. Но при это объект, скрывающийся за этим интерфейсом, может реализовывать какие-то дополнительные интерфейсы.
Для получения которых и требуется динамическая типизация.
ps
Возьмем стандартный пример - browser.
Browser работает с html-деревом.
У каждого элемента есть список элементов в него вложенных.
Вопрос: какой тип будет у элементов этого списка на этапе компиляции?
В этом дереве есть элементы: body, button, ссылка, каждая из них обладает своим набор методов и т.д.
Вопрос: как будет выглядеть код вида: найти кнопку с идентификатором 10 и произвести ее нажатие?
pps
Как только появляются полиморфные отношения, т.к. сразу необходима динамическая типизация.
Множество задач без полиморфных отношений очень мало.
А причем тут динамическая типизация? У Шурика вообще к IExplorer кастят без разговоров.
кастинг к IExplorer - это что тогда по твоему? статическая конвертация типа?
Ты имеешь в виду C#? Этот кастинг приведет к ошибке выполнения, если типы не соответствуют. Ты в своем примере говоришь о другом.
в том числе
> Этот кастинг приведет к ошибке выполнения, если типы не соответствуют
логично
> Ты в своем примере говоришь о другом.
в смысле?
Безусловный кастинг к IExplorer - ошибка.
2. Как в данном случае должен был выглядеть код?
Ну ты приведи код для своего примера.
>> Опять-таки - скорее всего ошибка проектирования.
> Вместо "громких" слов какие-нибудь факты и примеры будут?
Э-э-э. Мне показалось, что меня спросили хуйня ли это, или обычная практика. Я дал ответ, подразумевающий, что это хуйня. Просто в более вежливой форме.
> Покажи, пожалуйста, пальцем где говорилось про реальный тип объекта?
Показываю:
"Взять тот же паттерн "абстрактная фабрика" - такая фабрика никаким образом не сможет вернуть реальный тип объекта." - это кажется вы говорили.
> Везде говорилось, что методы возвращают/принимают интерфейс. Но при это объект,
> скрывающийся за этим интерфейсом, может реализовывать какие-то дополнительные
> интерфейсы. Для получения которых и требуется динамическая типизация.
C++ - не является языком с динамической типизацией. (Если я правильно понял, что вы под этим подразумеваете.) У С++ есть RTTI, которая это решает.
В заданном вопросе кажется лучше воспользоваться dynamic_cast. (см. Страуструп, 3 специальное издание, стр. 462) и проверить результат на ноль.
> Возьмем стандартный пример - browser.
> Browser работает с html-деревом.
> У каждого элемента есть список элементов в него вложенных.
> Вопрос: какой тип будет у элементов этого списка на этапе компиляции?
> В этом дереве есть элементы: body, button, ссылка, каждая из них обладает своим набор
> методов и т.д.
> Вопрос: как будет выглядеть код вида: найти кнопку с идентификатором 10 и произвести ее
> нажатие?
Тип - HTMLElement.
Надо найти элемент с HTMLElement.ID == 10, проверить кнопка ли это, и только после этого нажать. В противном случае вы когда-нибудь нажмете что-нибудь не то. Проверять можно разными способами. Например ввести поле типа элемента или использовать все тот же dynamic_cast. После чего сравнить производительность разных способов и оставить более производительный. Главная мысль, что при преобразовании указателя на родитель в указатель на потомок надо всегда задумываться о правомерности этого во всех возможных случаях в будущем. Особенно если вы делаете хороший браузер, который не падает каждые 5 минут.
> pps
> Как только появляются полиморфные отношения, т.к. сразу необходима динамическая
> типизация. Множество задач без полиморфных отношений очень мало.
Полагаю, что множество задач счетно. Т.е. вы хотите сказать, что множество задач решаемых без применения абстракции полиморфных отношений - конечно? Что-то мне так не кажется. Видимо вы просто такие больше любите или они вам чаще попадаются.
К тому же мне кажется, что полиморфные отношения не являются свойством задачи. Как и динамическая типизация впрочем. Это наши программисткие абстракции.
С уважением, Кучумов Андрей
Кучумов Андрей.
Что значит "хуйня"? без такого подхода часть задач просто не решается, взять ту же сериализацию. Функция десериализации тоже будет возвращать непонятно какой тип.
Это все равно, что сказать: деление - это хуйня, потому что деление может привести к ошибке, поэтому использовать надо только сложение, вычитание и умножение, а использование деления - это плохой стиль.
> Показываю:
> "Взять тот же паттерн "абстрактная фабрика" - такая фабрика никаким образом не сможет вернуть реальный тип объекта." - это кажется вы говорили.
данную фразу лучше заменить более общим утверждением: при создании разнородных объектов через "абстрактную фабрику" задекларированный возвращаемый тип у фабрики будет уже, чем набор интерфейсов поддерживаемых каждым конкретным объектом, создаваемым через эту фабрику.
> C++ - не является языком с динамической типизацией.
Можно поспорить. Я согласен, с тем что С++ ориентирован под статическую типизацию, но динамическую типизацию в C++ тоже можно использовать (осторожно, конечно).
> проверить кнопка ли это, и только после этого нажать
так метод "нажать" есть у каждого элемента? или есть только у типа Button (интерфейса IButton)?
если все-таки только у IButton-а (а не у каждого элемента то без явного преобразования типов не обойтись.
Получается, что мы имеем ровно туже ситуацию, что в первом посте.
IElement button = elements->GetElementById(10);
На вопрос, к каким интерфейсам можно преобразовывать кнопку, последуют в точности такой же ответ: смотри класс Button.
слово "можно" употребляется в смысле "имеет смысл".
например, так (если в C++-стиле):
dynamic_cast<IButton>(elements->getElementById(10->Click;
На вопрос, к каким интерфейсам можно преобразовывать кнопку, последуют в точности такой же ответ: смотри класс Button.
тк вопрос не такой. Вопрос аналогичный моему был бы такой, к каким типам я могу преобразовывать результат функции elements->GetElementById(10);
по-хорошему, если набор классов передается другому человеку, то такая ситуация должна быть прописана в документации. В моем случае документации вообще не было. Документацию всегда лень писать, поэтому надо меньше делать подобных ситуаций.
результат имеет смысл приводить к интерфейсам, которые реализуются хотя бы одним из элементов
а как это просмотреть в VS?
или еще чем-нибудь
При хорошей архитектуре может помочь Reverse Engineering.
> или еще чем-нибудь
Читать документацию?
> ошибке, поэтому использовать надо только сложение, вычитание и умножение, а
> использование деления - это плохой стиль.
Нет, я хочу сказать не это. Я хочу сказать, что недопустимо, что бы калькулятор при делении на ноль зависал. Короче исключительные ситуации нужно обрабатывать. Нельзя преобразовывать тип не проверяя правомочность этого преобразования.
Если я правильно понял - то в С# приведенный код сгенерирует исключение. Если оно обрабатывается, то я снимаю все свои возражения. Я перепутал с С++, в котором приведенная строка вызовет ошибку и предложил использовать dynamic_cast, т.е. собственно проверить правомочность преобразования.
А с тем, что возникает необходимость такого преобразования я вроде бы и не спорил.
В примере про кнопку - ключевое слово ПРОВЕРИТЬ, а только потом преобразовать.
Кучумов Андрей
У каждого элемента есть список элементов в него вложенных.
Вопрос: какой тип будет у элементов этого списка на этапе компиляции?
В этом дереве есть элементы: body, button, ссылка, каждая из них обладает своим набор методов и т.д.
Вопрос: как будет выглядеть код вида: найти кнопку с идентификатором 10 и произвести ее нажатие?
Вообще-то есть такой visitor pattern. Я к сожалению не посмотрел где понятнее, думаю любая подойдет...
Если я правильно понял - то в С# приведенный код сгенерирует исключение
Нет, вернет null.
Оставить комментарий
6yrop
Мне дали исходники на C# модулей, которые я должен использовать. И небольшой пример:IContext context = logon.CreateContext;
//Функция CreateContext возвращает объект типа IContext
public interface IContext
{
...
}
Потом идет вот такое преобразование типа
IExplorer explorer = context as IExplorer;
Я спрашиваю, к каким типам я могу приводить переменную context?
Мне ответили, смотри класс Context (не IContext). Почему? Отвечают: потому что он называется похожим образом.
По-моему какая-то хуйня, или это обычная практика?