Существующие реализации Eiffel скорее компилируют, чем интерпретируют.Поэтому оценка произвольных выражений не поддерживается.Обновление произвольных полей объекта с использованием заданных значений по-прежнему возможно с использованием классов отражения:
update_object (field_values: HASH_TABLE [ANY, STRING]; target: ANY)
-- Update fields of object `target` with values from `field_values`.
local
object: REFLECTED_REFERENCE_OBJECT
fields: like field_properties
position: like {REFLECTED_OBJECT}.field_count
do
create object.make (target)
fields := field_properties (object.dynamic_type)
across
field_values as v
loop
if attached fields [v.key] as f then
position := f.position
if {REFLECTOR}.field_conforms_to (v.item.generating_type.type_id, f.type_id) then
inspect object.field_type (position)
when {REFLECTOR_CONSTANTS}.integer_32_type then
object.set_integer_32_field (position, {INTEGER_32} / v.item)
when ... then
-- Other basic types.
when {REFLECTOR_CONSTANTS}.reference_type then
object.set_reference_field (position, v.item)
else
print ("Unhandled field type%N")
end
else
print ("Field type mismatch%N")
end
end
end
end
Приведенный выше код немного упрощен, поскольку он не обрабатывает типы SPECIAL
и TUPLE
, а также расширяемые пользователемтипы.Код опирается на вспомогательную функцию, которая записывает информацию о типе, так что в следующий раз ее не придется заново вычислять с нуля:
field_properties (type_id: like {TYPE [ANY]}.type_id):
HASH_TABLE [TUPLE [position: INTEGER; type_id: INTEGER], STRING]
-- Positions and types of fields indexed by their name
-- for a specified type ID `type_id`.
local
i: like {REFLECTOR}.field_count_of_type
do
Result := field_positions_table [type_id]
if not attached Result then
from
i := {REFLECTOR}.field_count_of_type (type_id)
create Result.make (i)
field_positions_table.force (Result, type_id)
until
i <= 0
loop
Result [{REFLECTOR}.field_name_of_type (i, type_id)] :=
[i, {REFLECTOR}.field_static_type_of_type (i, type_id)]
i := i - 1
end
end
end
field_positions_table: HASH_TABLE [HASH_TABLE
[TUPLE [position: INTEGER; type_id: INTEGER], STRING], INTEGER]
once
create Result.make (1)
end
Используя функцию update_object
и предполагая, что объект x
имеет поля foo
и bar
типов INTEGER_32
и detachable STRING_8
соответственно, следующий код
field_values: HASH_TABLE [ANY, STRING]
do
create field_values.make (10)
field_values ["foo"] := {INTEGER_32} 5
field_values ["bar"] := " bottles"
update_object (field_values, x)
print (x.foo)
print (x.bar)
выведет 5 bottles
независимо от предыдущего состояния объекта x
.