Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Динамическое обращение к методу toXMLString() экземпляра класса XML. (http://www.flasher.ru/forum/showthread.php?t=153646)

honest_man 06.04.2011 21:36

Динамическое обращение к методу toXMLString() экземпляра класса XML.
 
Друзья и, в чем я очень сомневаюсь, подруги, помогите понять почему не получается динамически обратиться к методу toString(). Вот код:
Код AS3:

package com.mywebsite {
        import flash.display.Sprite;
        import flash.events.*;
        import flash.net.*;
 
        public class TestClass extends Sprite
                {
                public static var myOwnXML :XML ;
                private static var urlLoader :URLLoader ;
 
                /* Метод-конструктор: */
                public function TestClass ():void
                        {
                        /* Загружаем XML-файл: */
                        var newRequest :URLRequest = new URLRequest("myXMLfile.xml");
                        urlLoader = new URLLoader(newRequest);
 
                        /* Регистрируем приемник для события "полная загрузка": */
                        urlLoader.addEventListener(Event.COMPLETE, completeListener);
                        }//Конец метода-конструктора
 
                /* Статический метод, выполняющийся сразу после полной загрузки XML-файла: */
                public static function completeListener (e:Event):void
                        {
                        myOwnXML = XML(urlLoader.data);
 
                        /* Цикл отображающий всех детей корневого элемента в XML-файле: */
                        for each (var XMLElement:XML in myOwnXML.*)
                                {
 
                                /* Рандом решает какой метод будет использоваться для отображения: */
                                var randomToStringOrToXMLString:String =
                                        (Math.random() < 0.5) ? "toString" : "toXMLString" ;
 
                                //Работают:
                                //trace( XMLElement.toString() );
                                //trace( XMLElement.toXMLString() );
 
                                //Не работает: (ПОМОГИТЕ!!!)
                                trace( XMLElement["toXMLString"]() );
                                }
                        }//Конец стат.метода textTypeListener
                }//Конец класса
        }//Конец пакета

Как бы, пытаюсь рандомно задать способ отображения, однако заминка- Почему-то не хочет динамически обращаться к методам toString()/toXMLString() экземпляра класса XML.

Я всегда думал что динамическое обращение работает везде, где работает обычное... Мозг в панике! =(((

Ах да, чуть не забыл, выдает вот эту ошибку:
Код:

TypeError: Error #1006: value is not a function.
        at com.mywebsite::TestClass$/completeListener()
        at flash.events::EventDispatcher/dispatchEventFunction()
        at flash.events::EventDispatcher/dispatchEvent()
        at flash.net::URLLoader/onComplete()


Wolsh 06.04.2011 22:19

Интересные виражи мысли)) То есть сначала Вы используете нетипизированный доступ, и тут же, как ни в чем не бывало – ставите скобки, как будто это функция и Вы ее вызываете. Но ведь обманутый Вами компилятор не может гарантировать не только то, что это Function, но даже – что такой член класса вообще есть.

Gaen 06.04.2011 22:40

Хм интересное поведение. Компилятор конечно гарантировать не может, но мы-то с вами знаем, что такие члены есть, и закомментированные работающие трейсы - тому подтверждение.

А задачу наверняка можно решить и так:
Код AS3:

var displayXML:Function = (Math.random() < 0.5) ? XMLElement.toString : XMLElement.toXMLString;
displayXML();

Код AS3:

(Math.random() < 0.5) ? XMLElement.toString() : XMLElement.toXMLString();


honest_man 06.04.2011 22:44

Это все так, но ведь компилятор тут вообще, к сожалению, не при чем. Ошибка происходит на этапе выполнения. Методы вышеупомянутые в классе XML определены (как бы, даже не знаю класса в котором toString() не был бы определен либо унаследован).

Значит проблема в чем-то другом, что-то в данном контексте мешает динамически обращаться к методу! =(

Добавлено через 22 минуты
GAIKER, Да, выдействительно правы,я как-то не подумал. Первый ваш вариант понравился больше :) Он закрученнее.

Однако всеравно хочется разобраться... У кого-то есть идеи?

wvxvw 06.04.2011 23:11

Потому что для XML перегружен оператор []. Он действует по следующему принципу: если есть ребенок с именем внутри скобок, то вернуть ссылку на ребенка, если нет ребенка - создать и вернуть ссылку на пустой XMLList, таким образом, если вы явно не вызываете функцию, вы будете создавать / получать ссылку на ребенка.

honest_man 06.04.2011 23:52

wvxvw, если бы я по случайности только что не нашел верный ответ я бы тоже принял Вашу точку зрения.

Квадратные скобки для экземпляров класса XML действительно играют важную роль и это, я так думаю, является одной из причин того, что для определения всех методов в класах XML и XMLList используется пространство имен AS3.

А теперь барабанная дробь...
Код AS3:

//Эта строка выдает ошибку на этапе выполнения:
trace( XMLElement["toXMLString"]() );

Код AS3:

//Следующие две строки верны и полностью идентичны по своему результату:
trace( XMLElement.toXMLString() );
trace( XMLElement.AS3::["toXMLString"]() );

При чем последняя строка может быть записана только так! "use namespace" не катит.

Это если кому интересно =)

wvxvw 07.04.2011 01:38

Ну так а что вы сделали? Вы же больше не обращаетесь динамически к XML. Вы обращаетесь динамически к пространству имен (т.е. не применяете оператор [] к XML). Ну а с пространством имен он так и работает.

honest_man 07.04.2011 16:03

Цитата:

Сообщение от wvxvw (Сообщение 987273)
Ну так а что вы сделали? Вы же больше не обращаетесь динамически к XML. Вы обращаетесь динамически к пространству имен (т.е. не применяете оператор [] к XML). Ну а с пространством имен он так и работает.

Так. Стоп... Я начинаю путаться в терминологии. В моем понимании, я обращаюсь к методу toXMLString() класса XML, а обращение происходит при помощи уточненного идентификатора AS3::["toXMLString"](), где "локальное имя" задается динамически (строковым литералом в данном случае).

Это я все веду к тому, что скобки [] вообще не при чем. Это легко доказывается следующим отрывком кода:
Код AS3:

trace( XMLElement.AS3::[0] ); //Выводит первого ребенка XML-элемента
trace( XMLElement.AS3::["toXMLString"]() ); //Выполняет метод toXMLString() над экземпляром
                                                            // класса XML, находящимся в переменной XMLElement

Следовательно скобки [] превосходно справляются и с идентификаторами детей и с динамическим обращением к методам.
Просто, наверное, причина моего конфуза была в том, что открытые пространства имен и динамическое обращение несовместимы... т.е. когда мы открываем пространство имен (при помощи use namespace), то всем неуточненным идентификаторам на этапе компиляции неявно добавляется приставка в виде: "открытоеПространствоИмен::", однако если неуточненный идентификатор записан при помощи динамического синтаксиса ["какая-тоПеременная"], то приставка не добавляется при компиляции.

нужно будет потэстить эту догадку

wvxvw 07.04.2011 19:58

> В моем понимании, я обращаюсь к методу toXMLString()
Нет :) в первом случае вы вызываете оператор [] с двумя аргументами XML и строка, и он возвращает вам новый XMLList, а во втором случае вы вызываете оператор [] с двумя аргументами - пространство имен AS3 примененное к объекту XML и строка, и он вам возвращает функцию.
псевдокод:
Код:

bracketsOperator(xml, "toXMLString") => XMLList
bracketsOperator(AS3(xml), "toXMLString") => function
где
AS3(xml) => { key: value }


Gaen 07.04.2011 23:55

wvxvw, но ведь в AVM2 нет понятия оператора :)
toXMLString, ["toXMLString"], AS3::toXMLString и AS3::["toXMLString"] - это просто разные QName, которые различаются типом (статический и рантаймовый) и набором неймспейсов (дефолтный и указанный явно). На уровне байткода указатель на функцию в итоге всегда ищется одинаково, эксперимент это подтверждает:

Код AS3:

var xmlTest:XML        = <testNode testAttribute="testValue">testContent</testNode>;
 
trace("1", xmlTest.toXMLString);
trace("2", xmlTest["toXMLString"]);
 
trace("3", xmlTest.AS3::toXMLString);
trace("4", xmlTest.AS3::["toXMLString"]);

Код:

    function str_fla:MainTimeline::str_fla:frame1():
    maxStack:4 localCount:1 initScopeDepth:10 maxScopeDepth:11
        getlocal0           
        pushscope           
        getlocal0           
        getlex                :XML
        pushstring            "<testNode testAttribute="testValue">testContent</testNode>"
        construct            (1)
        initproperty          :xmlTest
        findpropstrict        :trace
        pushstring            "1"
        getlocal0           
        getproperty          :xmlTest
        getproperty          private,,private,str_fla,str_fla,http://adobe.com/AS3/2006/builtin,adobe.utils,flash.accessibility,flash.desktop,flash.display,flash.errors,flash.events,flash.external,flash.filters,flash.geom,flash.media,flash.net,flash.printing,flash.profiler,flash.sampler,flash.system,flash.text,flash.text.engine,flash.ui,flash.utils,flash.xml,str_fla:MainTimeline,str_fla:MainTimeline,flash.display:MovieClip,flash.display:Sprite,flash.display:DisplayObjectContainer,flash.display:InteractiveObject,flash.display:DisplayObject,flash.events:EventDispatcher,Object:toXMLString
        callpropvoid          :trace (2)
        findpropstrict        :trace
        pushstring            "2"
        getlocal0           
        getproperty          :xmlTest
        pushstring            "toXMLString"
        getproperty          private,,private,str_fla,str_fla,http://adobe.com/AS3/2006/builtin,adobe.utils,flash.accessibility,flash.desktop,flash.display,flash.errors,flash.events,flash.external,flash.filters,flash.geom,flash.media,flash.net,flash.printing,flash.profiler,flash.sampler,flash.system,flash.text,flash.text.engine,flash.ui,flash.utils,flash.xml,str_fla:MainTimeline,str_fla:MainTimeline,flash.display:MovieClip,flash.display:Sprite,flash.display:DisplayObjectContainer,flash.display:InteractiveObject,flash.display:DisplayObject,flash.events:EventDispatcher,Object:null
        callpropvoid          :trace (2)
        findpropstrict        :trace
        pushstring            "3"
        getlocal0           
        getproperty          :xmlTest
        getproperty          http://adobe.com/AS3/2006/builtin:toXMLString
        callpropvoid          :trace (2)
        findpropstrict        :trace
        pushstring            "4"
        getlocal0           
        getproperty          :xmlTest
        pushstring            "toXMLString"
        getproperty          http://adobe.com/AS3/2006/builtin:null
        callpropvoid          :trace (2)
        returnvoid           
    0 Extras
    0 Traits Entries


wvxvw 08.04.2011 01:24

Эм... тогда понятия оператора нет нигде :) мы им пользуемся для удобства, чтобы не называть все функциями (хотя удобство сомнительное, но так уж исторически сложилось). QName - это объяснение того, как реализовано, но это не объясняет логику компилятора, почему он "решил" искать там, а не в другом месте. Он же QName создал не просто так, а чем-то руководствовался - вот это что-то, это и было оператором.

Gaen 08.04.2011 21:33

Так компилятор как раз не решает, где искать, он тупо фигачит неймспейс в байткод. Не указали - фигачит дефолтный, указали - фигачит указанный.
А вот чем руководствуется AVM2, когда ищет свойство в нескольких неймспейсах, т.е. как реализована команда getproperty - вот это вопрос :)


Часовой пояс GMT +4, время: 16:53.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.