Какие языки позволяют изменять идентичность объекта (не приведенного)? [закрытый]


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

Существуют ли языки программирования, которые позволяют такое?

3 2

3 ответа:

На самом деле, это то, что делается без проблем в Common Lisp, и в других диалектах Lisp, где CLOS (Common Lis Object System) был портирован. Вы используете change-class родовая функция для этого.

CLOS работает с несколькими методами диспетчеризации, поэтому метод не привязан к классу или объекту, это просто функция, которая выбирается в группе аналогичных функций WRT для типов (или тождеств) ее аргументов. При использовании change-class можно приводить аргументы так, как если бы вы создавали новый экземпляр, и данные, уже хранящиеся в объекте, останутся. Вот небольшая сессия, которая показывает, как это работает:
CL-USER> (defclass base ()
       ((name :initarg :name)))
#<STANDARD-CLASS BASE>
CL-USER> (defclass derived (base)
       ((age :initarg :age :initform 0)))
#<STANDARD-CLASS DERIVED>
CL-USER> (defvar foo (make-instance 'base :name "John Doe"))
FOO
CL-USER> (change-class foo 'derived :age 27)
#<DERIVED {100338F2D1}>
CL-USER> (with-slots (name age) foo
       (list name age))
("John Doe" 27)
CL-USER> (defvar bar (make-instance 'base :name "Baby Joe"))
BAR
CL-USER> (change-class bar 'derived)
#<DERIVED {10036CF6E1}>
CL-USER> (with-slots (name age) bar
       (list name age))
("Baby Joe" 0)
CL-USER> 

Если этого поведения по умолчанию недостаточно, вы можете определить метод на update-instance-for-different-class.

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

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

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

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