Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Как получить тип переменной? (http://www.flasher.ru/forum/showthread.php?t=158890)

Zolza 24.06.2011 19:18

Как получить тип переменной?
 
Думаю я далеко не первый кто такое спрашивает >_<

1) Нужно получить тип переменной(переменная еще не содержит значение)
2) Присвоить этой же переменной новое значение на основе полученного типа:
Код AS3:

someVar = new ПолученныйТип();

Что было:
Код AS3:

var spr:Sprite;
trace(typeof(spr)); // object
 
var str:String;
trace(typeof(str)); // string

Выводит object в случае со спрайтом. Значит не всегда будет работать так, как нужно. На этом мысль заканчивается.

Как получить заветный тип? Ну и далее по пункту 2, как такое делается?

dimarik 24.06.2011 20:15

Только объект может иметь какой-либо тип. Т.о. вы проверили тип объекта по ссылке.

goodguy 24.06.2011 20:38

Цитата:

Как получить заветный тип? Ну и далее по пункту 2, как такое делается?
Не представляю, где это может понадобиться в реальности, но сделать переменную, с типом данных, соответствующим другой переменной можно довольно просто:

Код AS3:

var yourVariable:SomeClass = new SomeClass();
 
var someCrap:Class = getDefinitionByName(getQualifiedClassName(yourVariable)) as Class;
var v:Object = new someCrap();
trace(v); // [object SomeClass]

но у меня вопрос, зачем создавать "пустую" переменную какого-то определенного типа?

S-ed 25.06.2011 00:56

Код AS3:

var spr:Sprite = new Sprite;
trace(spr); // [object Sprite]

Не надо сравнивать работу с классами и примитивными типами...

Nooob 25.06.2011 04:04

Код AS3:

var spr:Sprite = new Sprite;
trace(spr as Sprite); //[object Sprite]
trace(spr as String); //null


Zolza 25.06.2011 08:19

Цитата:

Сообщение от goodguy (Сообщение 1006294)
Не представляю, где это может понадобиться в реальности

Представьте: Есть неск-ко функций, использующих определенный набор объектов(переменных). Функции связаны, управляющий элемент ходит туда-сюда по этим функциям. Внутри функций по мере надобности инициализируются некоторые из объектов(переменных):
Код AS3:

function foo1(){
var1 = new var1Class();
var2 = new var2Class();
}
 
function foo2(){
var2 = new var2Class();
}

Чтобы в памяти не плодить кучи новых объектов, рационально их использовать повторно. То есть если объект уже получил значение, то его заново не создаем, а просто меняем необходимые свойства:
Код AS3:

function foo2(){
if(!var2) = new var2Class();
}

Вот на этом месте я задал себе вопрос - я что в каждой подобной foo№() должен такие проверки проводить? Не красиво и громоздко получается. Ладно, если будет одна точка входа в систему функций, там получится, что в любой момент времени известно, какие объекты созданы, и можно ручками написать такие проверки, сведя их к минимуму. А если точек входа несколько?
Цитата:

но у меня вопрос, зачем создавать "пустую" переменную какого-то определенного типа?
Пустые переменные - это еще не получившие значения поля класса, которые свои значения получают в функциях, пример выше.

Тут конечно можно сказать, мол сразу давай всем своим переменным значения и не мучайся. Но зачем мне иметь эти переменные тогда, когда они фактические еще нигде не используются?

Вот и чтобы избавится от копипаста одинаковых проверок, решено было вынести подобный алгоритм в отдельную функцию, которая(спасибо за инфу о нужных функциях) примерно выглядит вот так:
Код AS3:

function checkObj(...objs):void
{
        for(var i:int = 0; i < objs.length; i++)
        {
                if(!objs[i])
                {
                        assetClass = getDefinitionByName(getQualifiedClassName(obj[i])) as Class;
                        objs[i] = new assetClass();
                }
        }
}

Тут можно улыбнуться и расслабиться, но:

Код AS3:

import flash.display.Sprite;
 
var assetClass:Class;
var spr1:Sprite = new Sprite();
var spr2:Sprite;
 
assetClass = getDefinitionByName(getQualifiedClassName(spr1)) as Class;
trace(assetClass);
// [class Sprite]
 
 
// А если так:
assetClass = getDefinitionByName(getQualifiedClassName(spr2)) as Class;
// ReferenceError: Error #1065: Переменная null не определена.

Итог - переменная null в рамках такого алгоритма не то, чтобы получить значение не может. Даже считать из нее ссылку на класс нельзя. А значит я либо ничего не понял, либо придется оставить наполеоновские планы и решать проблему "в лоб". Мб кто-то с подобным сталкивался и подскажет, что тут еще можно сделать.

incoob 25.06.2011 10:03

У вас код
Код AS3:

if(!var2) = new var2Class();

компилируется?

Смотрите, что вы делаете: вначале пишете
Код AS3:

if(!objs[i])

. То есть objs[i] у вас, скорее всего, null (раз вы работаете с объектами). Потом вы передаете этот null в getQualifiedClassName. И что же вы хотите получить? Тем более вы не сможете инициализировать поле класса, так как не передаете в метод ссылку на него (а передаете вы null). Так что ваш подход реализовать невозможно таким способом.

Меняйте логику работы. Например, напишите геттер и везде используйте его, а не поле класса:
Код AS3:

                private var _sprite:Sprite;
 
                public function get sprite():Sprite
                {
                        if (!_sprite)
                        {
                                _sprite = new Sprite();
                        }
                        return _sprite;
                }

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

goodguy 25.06.2011 10:04

Zolza, может я опять что-то не совсем так понял, но для таких целей в АС3 есть звездочка * (wildcard).
т.е., создаем переменную без типа:
Код AS3:

var someVariable:*;

И, соответственно, можем в дальнейшем присвоить ей любой тип

nOobCrafter 25.06.2011 10:37

если классы ваши собственные а не нативные, то можете переопределить метод toString() и выводить то что вам угодно.. так же есть оператор проверки типа "is" (myValue is Sprite)

ChuwY 25.06.2011 14:59

Вместо
Код AS3:

getDefinitionByName(getQualifiedClassName(spr1)) as Class

проще использовать
Код AS3:

(spr1 as Object).constructor

Но здесь это не поможет.

Вообще, думаю, что подход неверен.
Почитайте про пул объектов.
Как раз то, что вам нужно.

-De- 25.06.2011 16:51

Я бы предложил такое:
Код AS3:

private var assetClassInfo:Object = {"var1":Sprite, "var2":Shape};
private var var1:Sprite;
private var var2:Shape;//да, дублирование, гадость, но жить можно
private function checkObj(...objs):void
{
        for each(var s:String in objs)
        {
                if(!this[s]) this[s] = new assetClassInfo[s];
        }
}
//использование
public function functionWithVar2(whatever:Whatever):WhateverElse
{
        checkObj("var2");
//var2 определена
}


Zolza 25.06.2011 17:08

Цитата:

У вас код
Код AS3:

if(!var2) = new var2Class();

компилируется?
Это опечатка в посте, будем считать ее в данном контексте псевдо-кодом :D
Цитата:

То есть objs[i] у вас, скорее всего, null (раз вы работаете с объектами). Потом вы передаете этот null в getQualifiedClassName. И что же вы хотите получить? Тем более вы не сможете инициализировать поле класса, так как не передаете в метод ссылку на него (а передаете вы null). Так что ваш подход реализовать невозможно таким способом.
Да, здесь я ошибся.
Цитата:

Zolza, может я опять что-то не совсем так понял, но для таких целей в АС3 есть звездочка * (wildcard).
т.е., создаем переменную без типа:
Про звездочку в курсе, это не мой случай. Нужно было получить инфу о типе, и на основе этого создать объект. Но инфу о типе из объекта null получить не удалось. Просто только сейчас пришло понимание того, что во время выполнения флэшке плевать, как я назвал переменную и какой тип данных она может иметь.
Цитата:

если классы ваши собственные а не нативные, то можете переопределить метод toString() и выводить то что вам угодно.. так же есть оператор проверки типа "is" (myValue is Sprite)
В случае с is или as нужно было бы делать свитчер, тут опять не мой случай. А вот с переопределением toString() идея интересная, возьму на заметку.
Цитата:

Вообще, думаю, что подход неверен.
Почитайте про пул объектов.
Как раз то, что вам нужно.
Беглый просмотр по пулу подтвердил, что это как раз то самое. Если у вас есть какие-нибудь интересные(спрятанные в закромах гугла и известные только избранным) ссылки на данную тему, поделитесь.
Цитата:

Я бы предложил такое
Я так понимаю это что-то вроде ассоциативного массива "имя переменной - тип этой переменной"?

semenyakinVS 25.06.2011 18:07

Может, поможет вот это обсуждение:

Проблема с typeOf()

S-ed 25.06.2011 22:01

Nooob
Null тк преобразование неудачное. Нельзя экземпляр класса в строку преобразовывать. Для этого есть toString().

Zolza
typeOf - как уже сказали - оператор, он различает всего 12 типов данных.

Вы тут обсуждает как "правильно" писать быдлокод?
Пытаетесь переложить функцию определения типа данных на компилятор?
Почему бы не ввести новый тип данных, вроде псевдо булевских переменных, или что-то из "стохастического программирования"?
Не хотел бы я разбираться в Вашем коде.

Пока не отработал конструктор - нет никакого класса.
В коде, опледеление типа нужно только для того чтоб компилятор работал как надо, чтоб не тратить часы на RTE.

Не нравятся типизированные переменные, пользуйтесь нетипизированными (динамическими).
(как вариант храните тип в имени переменной)

Zolza 26.06.2011 07:46

S-ed, какой быдлокод, какое стахановское программирование? Кто все эти люди?. Выяснили уже, что нужен мне пул объектов, или сделать через ассоциативный массив, как частный способ. Всё.

goodguy 26.06.2011 11:28

Цитата:

или сделать через ассоциативный массив
Через объект. В АС3 нет ассоциативных массивов

S-ed 26.06.2011 11:39

Zolza
Вы хотели пул объектов без самих объектов.

Вот через Object:
Код AS3:

var objectsArray:Object = new Object;
for(var i = 0; i < 5; i++){
    objectsArray["myVariableNum_" + i] = new Sprite;
}
 
for(var obj in objectsArray){
 trace(obj, "=", objectsArray[obj]);
}

Трейс:
Код:

myVariableNum_1 = [object Sprite]
myVariableNum_4 = [object Sprite]
myVariableNum_2 = [object Sprite]
myVariableNum_0 = [object Sprite]
myVariableNum_3 = [object Sprite]


-De- 26.06.2011 12:06

goodguy - Object, Dictionary и Array - ассоциативные массивы.
А вообще по-моему автору надо писать
Код AS3:

if(!var2) var2 = new var2Class();

и не страдать фигнёй. Это писать практически так же быстро, как и checkObj(var2), даже если там штук 5-10 таких переменных, но понятнее и работает быстрее.

S-ed 26.06.2011 12:15

-De-
Вы взяли код из #6? =)
"Человеку" хочется чтоб он мог отличить var2 от var1 когда передает их в функцию.

Zolza 26.06.2011 12:26

Цитата:

Сообщение от S-ed (Сообщение 1006600)
Вы хотели пул объектов без самих объектов.

Вообще, с моим подходом, я много чего хотел "без самих объектов". С этим разобрался.
Цитата:

Сообщение от -De-
А вообще по-моему автору надо писать...

У меня так и было. Только много и в разных местах. Захотелось сделать красиво, так сказать, "вынести общий множитель за скобки". Ну а ваше решение из поста 11 - как раз тот самый "общий множитель".

-De- 26.06.2011 12:57

Из #12 =)
Ему (как я понял) хочется гарантировать, что нужные переменные инициализированы, для чего он хочет написать функцию checkObj, в которую передавать эти самые переменные, чтоб там посмотрели, что там с этими переменными и проинитили, если надо. Неудобный подход.
Ещё можно попробовать группировать такие проверки. Типа инит-с-проверкой-1, инит-с-проверкой-2 итд. В них садить эти if(!var2)
И рекомендуется четко представлять типичные (а лучше все) сценарии инициализации и как именно получается выгода от того, что не инитится тупо всё сразу, из этого обычно можно придумать подход лучше.
PS: Пул по-моему тут не в кассу, потому что в одном пуле сидят обьекты одного типа.

S-ed 26.06.2011 13:17

-De-
Object - динамический класс, можно пихать любые переменные.
Код AS3:

var objectsArray:Object = new Object;
for(var i = 0; i < 5; i++){
        if(i != 4){
                objectsArray["myVariableNum_" + i] = new MovieClip;
        }
        else{
                objectsArray["myVariableNum_" + i] = new Sprite;
        }
}
 
for(var obj in objectsArray){
 trace(obj, "=", objectsArray[obj]);
}

Код:

myVariableNum_3 = [object MovieClip]
myVariableNum_1 = [object MovieClip]
myVariableNum_4 = [object Sprite]
myVariableNum_2 = [object MovieClip]
myVariableNum_0 = [object MovieClip]


-De- 26.06.2011 14:06

Дык. Это к чему?

Zolza 26.06.2011 15:19

Цитата:

Сообщение от -De- (Сообщение 1006612)
Дык. Это к чему?

Я так понял, что S-ed предлагает полностью динамический подход. Где в качестве карты типов используются просто индексы.


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

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