Неожиданное поведение с accessors = true для компонента
Я пытаюсь использовать синтезированные аксессоры для компонента на Lucee (хотя эта проблема, похоже, одинакова и для ColdFusion).
Код репрограммы:
// Person.cfc
component accessors=true {
property firstName;
property lastName;
function init(firstName, lastName){
variables.firstName = arguments.firstName;
variables.lastName = arguments.lastName;
}
}
И вызывающий код:
// person.cfm
person = new Person("Abigail", "Bowen");
writeDump(person);
Обратите внимание, что здесь я не использую синтезированные аксессоры, я просто устанавливаю значения аргументов в переменные с переменными с одинаковым именем.
Однако, когда я запускаю этот код, я вижу следующее:
![Dump output showing properties]()
Обратите внимание, как свойства были заполнены. Там нет проблем с этим, но я явно не понимаю, как должен работать флаг accessors
. Я думал, что это просто предназначено для синтеза некоторых методов доступа для меня (что у него есть), но все.
Также обратите внимание, что если я изменяю определение CFC, чтобы не устанавливать accessors в true, тогда дамп показывает это:
![Dump with no properties]()
Так что никаких синтезированных аксессуаров (как и ожидалось), но и теперь свойства даже не отображаются (со значениями переменных или нет).
Я действительно не понимаю это сочетание свойств и настроек аксессоров? Разумеется, настройка аксессоров должна влиять только на то, создаются ли эти методы доступа?
Если бы я видел это только на одной из платформ, я бы, вероятно, отказался от того, как writeDump()
интерпретирует определения свойств. Но поведение ColdFusion 11 одинаково, поэтому на самом деле кажется, что есть какая-то разница в поведении, которое я не совсем понимаю.
Кто-нибудь может это объяснить? Есть ли какие-либо документы, которые объясняют это? Если нет... гм... почему бы и нет?
Моя основная проблема заключается в том, что значения свойств не сохраняются "правильно" и могут вызвать у меня проблемы, когда я реализую больше кода.
UPDATE:
По крайней мере, в ColdFusion, это просто изменение в поведении writeDump()
, потому что если есть атрибуты для свойств (независимо от того, установлен ли флаг accessors
), значения свойств начинают отображаться в дампе. Однако это не так на Lucee, поэтому там есть вопросительный знак.
Ради полного раскрытия, этот вопрос представляет собой резюме вопроса, который я также задал в своем блоге ( " CFML: попытка понять аксессоры" ). Дублирование преднамеренно, так как мой блог получает другую аудиторию от той, что принадлежит этому сайту.
Ответы
Ответ 1
Без accessors=true
объявления property
- это просто метаданные.
С accessors=true
объявления property
запускают генерацию геттеров/сеттеров и, таким образом, property
представляет собой как элемент variables
scope , так и пару методов.
В вашем конструкторе вы назначаете элементы области variables
- которые будут такими же, как с использованием сгенерированных сеттеров, - и когда CFML выгружает компонент, он видит метаданные property
и сгенерированные геттеры и так далее он отображает значения, которые имеют эти свойства (поскольку он может легко и безопасно вызвать сгенерированные геттеры).
Ответ 2
Это вызвало ACF9. До тех пор определение в документах свойств было правильным: объявления cfproperty только метаданные. (см. дамп (getMetaData()).
В ACF9 это было не совсем корректно по трем причинам:
-
С помощью accessors=true
для каждого свойства генерируется геттер и сеттер, а эти аксессоры читают и записывают в область переменных. Cfproperty больше не только метаданные, но и прямо влияет на поведение экземпляра. Мне нравится думать об этом как о CF-версии реальных свойств OO (введенных случайно).
-
Реализация cfdump изменяет свое поведение на основе объявлений свойств. Если property name;
определено и метод getName()
существует (сгенерирован или реализован), он добавляется в раздел свойств дампа.
-
Атрибуты свойств управляют ORM.
Поскольку я узнал эти функции, я проектирую все мои (общедоступные) CFC, чтобы выглядеть правильно при сбрасывании, например. Я использую только объявление свойства (+ геттеры), когда хочу, чтобы оно было видимым. Кроме того, вы можете реализовать методы, которые вызывается только дампами и ничего не стоят при создании экземпляра:
struct function getDebug(){
var x = doSomethingExpensive();
return { "Foo":f, "Bar":b, "Baz":x };
}
//or for a user iterator
string function getName(){
return qUsers.name[index];
}
Некоторые предостережения, которые я знаю:
- ACF всегда вызывает геттеры из дампов, в то время как в Railo/Lucee отображается значение из области переменных. Таким образом, приведенные выше примеры (
getDebug()
и getName()
) не работают на Railo/Lucee.
- Если получатель не является общедоступным или приводит к ошибке, дамп показывает пустую строку для свойства (не уверен здесь, возможно, свойство отсутствует).
- Объявления свойств в расширенных CFC игнорируются. Это дало мне некоторую головную боль в объектах ORM, которые используют наследование, потому что вам не разрешено объявлять свойство дважды. Таким образом, у вас нет возможности показать свойство, определенное в базовых CFC.
- Railo/Lucee, похоже, игнорирует типы собственности. Все accessor принимают и возвращают только строки (см. GetMetaData()).
- Незначительный: в ACF при активации аксессуаров, но деактивируйте getter и setter для свойства:
property name="user" getter="false" setter="false";
он все еще отображается на дампе - он должен быть скрыт.