Почему заменяемые в горячем режиме vtables не являются популярной функцией языка?

В объектно-ориентированном программировании иногда хорошо смочь изменить поведение уже-созданного-объекта. Конечно, это может быть сделано с относительно подробными методами, такими как стратегическая модель. Однако иногда было бы хорошо просто полностью изменение тип объекта путем изменения vtable указателя после инстанцирования. Это было бы безопасно, если, принимая Вы переключаетесь от класса A до класса B:

  1. класс B является подклассом класса A и не добавляет новых полей, или
  2. класс B и класс A имеют тот же родительский класс. Ни сделайте что-либо кроме виртуальных функций переопределения от родительского класса. (Никакие новые поля или виртуальные функции.)
  3. В любом случае A и B должен иметь те же инварианты.

Это hackable в C++ и языке программирования D, потому что указатели могут быть произвольно брошены вокруг, но это так ужасно и твердо следовать, что я боялся бы делать это в коде, который должен быть понят под кем-либо еще. Почему высокоуровневый путь не состоит в том, чтобы сделать, это обычно обеспечивало?

5
задан dsimcha 20 December 2009 в 16:35
поделиться

5 ответов

Потому что мышление большинства разработчиков языков слишком статично.

Хотя такие возможности опасны в руках программистов, они являются необходимыми инструментами для разработчиков библиотек. Например, в Java можно создавать объекты без вызова конструктора (да, вы можете!), Но это право предоставляется только разработчикам библиотек. Тем не менее, многие функции, из-за которых разработчики библиотек убили бы, увы, невозможны в Java. C #, с другой стороны, добавляет все больше и больше динамических функций в каждую версию. Я действительно с нетерпением жду появления всех замечательных библиотек, которые можно создать с помощью предстоящего DLR (динамического языка выполнения).

В некоторых динамических языках, таких как Smalltalk (а также, насколько я знаю Perl и Python, но не Ruby), это вполне возможно изменить класс объекта. В Pharo Smalltalk это достигается с помощью

object primitiveChangeClassTo: anotherObject

, который изменяет класс объекта на класс anotherObject . Обратите внимание, что это не то же самое, что объект становится: anotherObject , который обменивает все указатели обоих объектов.

3
ответ дан 14 December 2019 в 08:52
поделиться

Вы можете сделать это на языках более высокого уровня - см. Сообщение Smalltalk "стать". Тот факт, что эту функцию почти невозможно правильно использовать даже в ST, может быть причиной того, что статически типизированные языки, такие как C ++, не поддерживают ее.

1
ответ дан 14 December 2019 в 08:52
поделиться

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

Заплатка обезьяны (также пишется monkey-patch, MonkeyPatch) - способ расширить или изменить код времени выполнения динамические языки (например, Smalltalk, JavaScript, Objective-C, Ruby, Perl, Python, Groovy и т. Д.) Без изменения исходный исходный код.

0
ответ дан 14 December 2019 в 08:52
поделиться

Вы можете сделать это на Python, изменив атрибут instance __ class __ :

>>> class A(object):
...     def foo(self):
...         print "I am an A"
...
>>>
>>> class B(object):
...     def foo(self):
...         print "I am a B"
...
>>>
>>> a = A()
>>> a.foo()
I am an A

>>> a.__class__
<class '__main__.A'>

>>> a.__class__ = B
>>>
>>> a
<__main__.B object at 0x017010B0>
>>> a.foo()
I am a B

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

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

2
ответ дан 14 December 2019 в 08:52
поделиться

Перефразируя документацию XoTcl, это происходит потому, что большинство языков, объявляемых «объектно-ориентированными», не являются - они ориентированы на классы. Похоже, что миксины XoTcl, миксины Ruby и роли Perl6 обеспечивают функциональность, которую вы ищете.

1
ответ дан 14 December 2019 в 08:52
поделиться