2015-02-25 3 views
11

Я пытаюсь использовать синтезированные аксессоры на компоненте на Lucee (хотя эта проблема, похоже, одинакова и для ColdFusion).Неожиданное поведение с accessors = true для компонента

Репро код:

// 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 для не набор аксессорах к истинным, то дамп показывает это:

Dump with no properties

Так что нет синтезированные аксессоров (как и ожидалось), но и сейчас свойства даже не отображаются (со значениями с переменными или нет).

Я действительно не понимаю это сочетание «свойств» и настроек аксессуаров? Разумеется, настройка аксессоров должна влиять только на то, создаются ли эти методы доступа?

Если бы я видел это только на одной из платформ, я бы, вероятно, поставил его под каприз, как writeDump() интерпретирует определения свойств. Но поведение ColdFusion 11 одинаково, поэтому действительно кажется, что есть некоторая разница в поведении, которое я не совсем понимаю.

Может ли это объяснить это? Есть ли какие-либо документы, которые объясняют это? Если нет ... гм ... почему бы и нет?

Основная проблема заключается в том, что значения свойств не сохраняются «должным образом» и могут вызвать у меня проблемы, когда я реализую больше кода.

ОБНОВЛЕНИЕ: По крайней мере, на ColdFusion, по-видимому, чтобы быть просто изменением в поведении writeDump() «ы, потому что если есть геттеры для свойств (или не установлен, то accessors флага), то значение свойств начинает появляться в дампе. Однако это не относится к Lucee, поэтому там есть вопросительный знак.

Ради полного раскрытия, этот вопрос представляет собой резюме вопроса, который я также задал в своем блоге («CFML: trying to understand accessors»). Дублирование преднамеренно, так как мой блог получает другую аудиторию от того, что на этом сайте.

ответ

10

Без accessors=true объявления property - это всего лишь метаданные.

С accessors=true, то property заявлений вызывают генерацию геттеров/сеттеров и, таким образом property является как элементом variables объема и пара методов.

В конструкторе, вы назначаете к variables пунктам области видимости, - которые будут таким же, как с помощью сгенерированных сеттеров - и когда CFML отвалами компонента, он видит property метаданных и сгенерированные методы получения и поэтому отображает значения этих свойств (поскольку он может легко и безопасно вызвать генерируемые геттеры).

+1

Да, это то, что кажется (см. Мое обновление). Однако поведение Люси немного расходится с ColdFusion. Думаю, Люси ищет настройки * и * методы; CF просто ищет методы. И разница полностью в поведении дампа, а не что-то еще. –

+0

Это только случай поведения конструктора CF9? В CF9 init() стал истинным конструктором в том случае, если он у вас есть, он автоматически вызывается, когда вы используете новое ключевое слово, то же, что и в Java. То же самое произойдет, если вы переименуете init() в Person(). Если вы, ребята, были правы, это также произойдет, если вы использовали другое имя функции, а это не так. Это происходит только тогда, когда CF работает как конструктор. – ialexander

2

Это придумал ACF9. До тех пор определение в документах свойств было правильным: объявления cfproperty только метаданные. (См свалка (GetMetadata())

В ACF9 это не совсем верно больше по 3 причинам:.

  1. С accessors=true геттер и сеттер генерируется для каждого свойства и те аксессоров чтения и записи к области переменным областью.Cfproperty - это не только метаданные, но и оказывает прямое влияние на поведение экземпляра. Мне нравится думать о нем как о версии реальных прав OO (введенных случайно).

  2. c Реализация fdump изменяет свое поведение на основе объявлений свойств. Если определено property name;, и существует метод (getName()) (сгенерирован или реализован), он добавляется в раздел свойств дампа.

  3. Атрибуты свойств управляют 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.
  • Если получатель не является общедоступным или приводит к ошибке, дамп показывает пустую строку для свойства (не уверен здесь, возможно, вместо этого отсутствует свойство).
  • Объявления свойств в расширенных ХФУ игнорируются. Это дало мне некоторую головную боль в объектах ORM, которые используют наследование, потому что вам не разрешено объявлять свойство дважды. Таким образом, у вас нет возможности показать свойство, определенное в базовых ХФУ.
  • Railo/Lucee, похоже, игнорирует типы собственности. Все accessor принимают и возвращают только строки (см. GetMetaData()).
  • Незначительный: в ACF при активации аксессуаров, но деактивируйте геттер и сеттер для свойства: property name="user" getter="false" setter="false"; он все еще виден на свалке - он должен быть скрыт.