Неожиданное поведение с 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"; он все еще отображается на дампе - он должен быть скрыт.