Когда использовать информацию о типе времени выполнения? - PullRequest
5 голосов
/ 05 октября 2009

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

Например, если подклассы являются узлами DOM, и если алгоритм должен вставить дочерний узел, этот алгоритм отличается в зависимости от того, является ли родительский узел элементом DOM (который может иметь дочерние элементы) или текстом DOM (который не может ): и поэтому метод insertChildren может быть виртуальным (или абстрактным) в базовом классе DomNode и реализован по-разному в каждом из подклассов DomElement и DomText.

Другая возможность - дать экземплярам общее свойство, значение которого можно прочитать: например, алгоритм может прочитать свойство nodeType базового класса DomNode; или для другого примера у вас могут быть различные типы (подклассы) сетевых пакетов, которые имеют общий заголовок пакета, и вы можете прочитать заголовок пакета, чтобы увидеть, какой это тип пакета.

Я не очень много использовал информацию типа времени выполнения, в том числе:

  • Ключевые слова is и as в C #
  • 1020 * понижающее приведение *
  • Метод Object.GetType в точечной сети
  • Оператор typeid в C ++

Когда я добавляю новый алгоритм, который зависит от типа подкласса, я вместо этого склоняюсь к добавлению нового виртуального метода в иерархию классов.

Мой вопрос: когда уместно использовать информацию типа времени выполнения вместо виртуальных функций?

Ответы [ 5 ]

5 голосов
/ 05 октября 2009

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

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

3 голосов
/ 05 октября 2009

В C ++, среди некоторых других непонятных случаев (которые в основном связаны с худшими вариантами проектирования), RTTI является способом реализации так называемых мульти методов .

1 голос
/ 05 октября 2009

Эти конструкции ("is" и "as") очень знакомы разработчикам на Delphi, поскольку обработчики событий обычно понижают объекты до общего предка. Например, событие OnClick передает единственный аргумент Sender: TObject независимо от типа объекта, будь то TButton, TListBox или любой другой. Если вы хотите узнать что-то больше об этом объекте, вам нужно получить к нему доступ через «как», но чтобы избежать исключения, вы можете проверить его с «is» раньше. Это снижение допускает привязку типов и объектов к объектам, что было бы невозможно при строгой проверке типов классов. Представьте, что вы хотите сделать то же самое, если пользователь нажимает кнопку или ListBox, но если они предоставляют нам разные прототипы функций, невозможно связать их с одной и той же процедурой.

В более общем случае объект может вызывать функцию, которая уведомляет, например, об изменении объекта. Но заранее это оставляет пункт назначения возможность узнать его «лично» (через, как и есть), но не обязательно. Он делает это, передавая себя как наиболее общего предка всех объектов (TObject в случае Delphi)

0 голосов
/ 05 октября 2009

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

Пункт 3. Специализированные универсальные алгоритмы Использование проверки типа во время выполнения

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

Все это здорово, потому что ты пишешь меньше кода Однако иногда более общий означает не принимать Преимущество более конкретное, но явно превосходный алгоритм. C # языковые правила принимают это во внимание. Все, что вам нужно, это чтобы вы узнали что ваш алгоритм может быть больше эффективен, когда параметры типа иметь большие возможности, а затем написать этот конкретный код. Более того, создавая второй общий тип, который определяет различные ограничения не всегда работает общий экземпляры основаны на тип объекта во время компиляции и не тип времени выполнения. Если вам не удастся принять это во внимание, вы можете пропустить возможная эффективность.

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

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

0 голосов
/ 05 октября 2009

dynamic_cast <>, если я правильно помню, зависит от RTTI. Некоторые неясные внешние интерфейсы могут также полагаться на RTTI, когда объект передается через указатель void (по любой причине , что может произойти).

Как говорится, я не видел typeof () в дикой природе за 10 лет работы по поддержке pro C ++. (К счастью.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...