Eiffel: однажды функция имеет общий или привязанный результат. Попытка создания констант
Я пытаюсь создать цвета для регистрации в терминале, чтобы мои ошибки были понятнее. При этом мне кажется очевидным, что мне придется создавать константы, подобные следующим. Поскольку я не хочу создавать экземпляр каждый раз, когда я вызываю свою константу, для меня имеет смысл сделать что-то подобное, но компилятор, похоже, не имеет той же концепции, что и я...
A once function has generic or anchored result
что такое anchored
результат?
Поскольку у компилятора всегда последнее слово, а у меня передний план, почему я ошибаюсь, и он прав?
class
TERMINAL_COLOR
create
make
feature -- Initialization
make (a_fg: like foreground; a_bg: like background)
do
foregound := a_fg
background := a_bg
end
feature -- Status report
foreground: INTEGER
background: INTEGER
feature -- Colors
Black: like Current
once -- compiler doesn't agree with me
create Result.make (30, 40)
ensure
instance_free: class
end
end
2 ответа
Тип привязки - это когда вы используете "подобную функцию" (обратите внимание, что вы также можете использовать "like {FOO}.bar").
Кроме того, не забывайте, что "Один раз" - "один раз на класс" (не по типу). Вот почему тип результата для функции Once не может использовать какой-либо формальный шаблон. Например
class FOO [G]
feature
bar: STRING
once
Result := generating_type
end
end
(create {FOO [INTEGER]}).bar
вернет тот же объект, что и (create {FOO [STRING]}).bar
,
Итак, теперь, если bar
вернется G
в классе FOO это вызовет проблемы, поскольку нет способа вернуть значение, соответствующее любому формальному (INTEGER, STRING, ...).
Поэтому общий тип запрещен для одного типа результата.
Та же логика применяется к типу привязки, такой как like feature_name
, как feature_name
может быть переопределено в потомке с другими типами.
Действительно, если функциям не разрешено возвращать значение привязанного типа или формального универсального типа. Причина заключается в семантике функции Once: ее тело выполняется только один раз (я опускаю более сложные случаи с рекурсией) независимо от текущего типа объекта.
В вашем примере было бы возможно иметь потомка класса TERMINAL_COLOR
, сказать, TOUCH_PAD_COLOR
(что бы это ни значило):
class
TOUCH_PAD_COLOR
inherit
TERMINAL_COLOR
create
make
feature
touch_color: like Current
-- Color for visual indication of user interaction.
...
end
Давайте посмотрим, что происходит в следующем коде:
t: TERMINAL_COLOR
p: TOUCH_PAD_COLOR
...
t := {TERMINAL_COLOR}.black
p := {TOUCH_PAD_COLOR}.black
Так как black
возвращается like Current
оба назначения действительны: тип black
является TERMINAL_COLOR
в первом звонке и TOUCH_PAD_COLOR
- во-вторых. Тем не менее, тело функции black
выполняется только один раз, а именно при первом вызове. И тип вычисляемого объекта TERMINAL_COLOR
, Во втором присваивании ранее вычисленный объект возвращается без выполнения тела функции black
, Тип объекта остается прежним: TERMINAL_COLOR
, Но теперь этот объект прикреплен к сущности p
типа TOUCH_PAD_COLOR
, Звонить на p
например, p.touch_color
приведет к сбою, потому что нет никакого метода touch_color
в классе TERMINAL_COLOR
,
Что касается терминологии, привязанные типы обозначают типы, объявленные в терминах некоторых других объектов. Например, like Current
относится к типу текущего класса.
Отказ от ответственности. Существуют разные виды некогда функций, в приведенном выше сценарии рассматривается наиболее распространенный случай.