В методе объекта обратиться к своему свойству можно 4-мя способами. Когда какой предпочтительней и какая между ними разница?Будем рассматривать примеры обращения к свойству объекта на классе
Class Test.NewClass1 Extends %Persistent [ ClassType = persistent] { Property Prop As %String; Method Meth() { w ..Prop w ##this.Prop w %this.Prop w i%Prop } }и проводить различные к нему добавления для исследования. Исследование поведения можно провести самостоятельно, открыв и просмотрев получающиеся после трансляции коды int-рутин.
Обращение через ..PropName
При трансляции такого обращения компилятор проверяет наличие такого свойства и что транслируется метод объекта, а не класса. Если для этого свойства не было определения property getter или property setter, то транслируется в оптимизированный код прямого доступа к слоту (раннее связывание), иначе код транслируется в код вызова значения через объектный движок (позднее связывание). Что интересно - достаточно объявления геттера без сеттера и наоборот, трансляция все равно приводит к позднему связыванию.
Если обращаемся к свойству в классе наследнике, в котором определяем геттер или сеттер, то при трансляции методов все базовые методы, унаследованные им, автоматически перетранслируются в этом классе и получаем позднее связывание.
Обращение через %this.PropName
Это синтаксис обращения к свойству объекта, на который указывает локальная переменная
При трансляции не проверяется что это за переменная, является ли объектом, какого типа, есть ли у этого типа это свойство, и каков контекст трансляции. Этот факт можно использовать, например, в методах классов или в обычных рутинах, которые вызываются из методов объектов и по переменной
Код обращения через
Обращение через ##this.PropName
Судя по поведению транслятора, использование директивы препроцессора
В версии cache постарше, где есть code complete (например,
Обращение через i%PropName или r%PropName
Обращение к свойству через
$zobjval(,3,0,3,3)Самостоятельно обращаться к функции $zobjval, мягко говоря, не рекомендуется.
При трансляции этой формы игнорируется наличие геттера и сеттера, в том числе в классе-наследнике. Поэтому такая форма используется в самих геттерах и сеттерах для предотвращения зацикливания. При трансляции этой формы компилятор проверяет контекст трансляции - это должен быть метод объекта, наличие такого свойства и немного типизацию.
Если объект есть свойство datatype класса, то нужно использовать форму
Синтаксически не поддерживается обращение через
так же возможно обращению к свойству объекта через $this.Property, но работать это будет только в контексте объекта, в коде classmethod в специальной переменной $this уже будет не объект а имя класса. Поэтому использовать $this нужно очень внимательно.
ОтветитьУдалитьЕсли имя свойства у нас в виде строки, то получить значение свойства через функцию $zobjproperty, которая в последствии была заменена на $property(obj, "property"), для методов так же есть функции $method и $classmethod.
При разработке класса еще есть возможность указать специальный метод, который будет вызываться при обращении к неописанным свойствам класса, это метод %DispatchGetProperty, более подробно в документации (http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GOBJ_dynamicdispatch)
кстати такой вариант тоже рабочий, но не стоит так делать, только в исключительных случаях, например при работе с JSON
Property "Some-Property" As %String;
write .."Some-Property"