Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 22.02.2012, 23:29
in4core вне форума Посмотреть профиль Отправить личное сообщение для in4core Найти все сообщения от in4core
  № 1  
Ответить с цитированием
in4core
 
Аватар для in4core

Регистрация: Mar 2009
Сообщений: 4,219
Записей в блоге: 14
По умолчанию Первое обращение к статику

Товарищи увы, открыл для себя интересную вещь, о которой даже не знал, а может быть, проблема в другом , вообщем :

Есть класс загрузки скинов , и класс в котором идет работа с элементами скина.
Рассмоьтрим второй класс

Код AS3:
class ManagerSkin {
 
private static var element:MovieClip = Skins.getElement();
 
}
Так вот, теперь рассмотрим ситуацию, что инстанс ManagerSkin еще не готов , а так же Skins не прошел инициализацию, напишем :
ManagerSkin.setVar(0) // некий метод не имеющий отношение к Skins

В итоге после этого, как только инстанс будет создан и будет обращение к element мы получим ошибку. (1009)

Тоесть вывод : как только мы первый раз обращаемся к классу со статическими переменными - ВСЯ его статика сразу же инициализируется.

Честно говоря, я думал, что инициализация статики происходит ТОЛЬКО после обращения к ней напрямую, и не зависит от того, что ты стучишься к другим переменным.
__________________
Марк Tween

Старый 22.02.2012, 23:44
expl вне форума Посмотреть профиль Отправить личное сообщение для expl Найти все сообщения от expl
  № 2  
Ответить с цитированием
expl

блогер
Регистрация: Feb 2006
Сообщений: 1,474
Записей в блоге: 3
Инициализация статик классов непредсказуема.
Но можно гарантировать выполнение кода перед обращением ленивой инициализацией:
Код AS3:
public static getElement():MovieClip
{
    if (!_inited)
    {
        init();
    }
    ...
    return _element;
}
Соответсвенно все присваивания статичным полям поместить в этот init().
Однако, если у тебя есть несколько статических классов, ссылающихся при инициализации друг на друга - разработка обещает быть весёлой

У нас в проекте существуют и статичные классы без состояния(т.е. без методов) - с ними таких проблем не возникает, и с минимальным состоянием - это статические фабрики объектов.
Но у нас нет одного статического класса, которому нужна инициализация другого статического - это перебор, нельзя так активно генератор косяков под названием "статичный класс" использовать.

Ещё можно у каждого статик-класса создать метод init(). И вызвать при старте приложения все init() в нужном порядке - это сделает код гораздо прозрачнее.
Но все присваивания полям должны быть либо линивыми либо в коде init()!


Последний раз редактировалось expl; 22.02.2012 в 23:52.
Старый 22.02.2012, 23:58
in4core вне форума Посмотреть профиль Отправить личное сообщение для in4core Найти все сообщения от in4core
  № 3  
Ответить с цитированием
in4core
 
Аватар для in4core

Регистрация: Mar 2009
Сообщений: 4,219
Записей в блоге: 14
На самом деле случайно нарвался на этот момент. У меня суть в том, что часть классов ( типа синглтон ) имеют только 1 инстанс, соотв в таких случаях я по обычке ВСЕ переменные такого класса задаю как статик или статик конст ( ну ежели и переменная не будет меняться ) при этом класс не статичный , это касается тока переменных.
А тут случайно вызвал утилитный метод отдельно и попал в просак) искал ошибку часа 1.5 ))
__________________
Марк Tween

Старый 23.02.2012, 00:04
expl вне форума Посмотреть профиль Отправить личное сообщение для expl Найти все сообщения от expl
  № 4  
Ответить с цитированием
expl

блогер
Регистрация: Feb 2006
Сообщений: 1,474
Записей в блоге: 3
Цитата:
У меня суть в том, что часть классов ( типа синглтон ) имеют только 1 инстанс, соотв в таких случаях я по обычке ВСЕ переменные такого класса задаю как статик или статик конст ( ну ежели и переменная не будет меняться ) при этом класс не статичный , это касается тока переменных.
Если класс синглтон, зачем все его поля делать статичными? Они же все равно 2 раза _не_ проинициализируются. А если они будут инициализироваться в конструкторе синглтона или как присвоения обычным полям - то есть полная гарантия, что при обращении к синглтону через getInstance все они будут проинициализированы. Со статикой такой гарантии нет.

А вот если проблемы возникают с внешней либой построенной на статичных классах - опиши по-подробнее - тут придется выкручиваться по ситуации.

Старый 23.02.2012, 00:11
in4core вне форума Посмотреть профиль Отправить личное сообщение для in4core Найти все сообщения от in4core
  № 5  
Ответить с цитированием
in4core
 
Аватар для in4core

Регистрация: Mar 2009
Сообщений: 4,219
Записей в блоге: 14
expl да нет, проблем как бы нету, просто вот наткнулся на эту фичу, раньше об ней даже не знал.
__________________
Марк Tween

Старый 23.02.2012, 00:21
Aquahawk вне форума Посмотреть профиль Отправить личное сообщение для Aquahawk Посетить домашнюю страницу Aquahawk Найти все сообщения от Aquahawk
  № 6  
Ответить с цитированием
Aquahawk
 
Аватар для Aquahawk

Регистрация: Nov 2010
Адрес: Москва
Сообщений: 915
Записей в блоге: 4
Отправить сообщение для Aquahawk с помощью ICQ Отправить сообщение для Aquahawk с помощью Skype™
Цитата:
как только мы первый раз обращаемся к классу со статическими переменными - ВСЯ его статика сразу же инициализируется.
Да истинно так. Советую прочитать avm2 overview многие подобные вопросы отпадут. В частности то что вызывается при первой инициализации называется cinit и туда свалится весь код инициализации, кроме константных значений некоторых типов, они в структуре класса будут представлены в виде значений по умолчанию.
Причём cinit это обычный метод, туда можно код понаписать:
Код AS3:
class ManagerSkin {
 
private static var element:MovieClip = Skins.getElement();
trace("hello from cinit");
 
}
Чтобы это лучше понять можно взять что-нибудь из хороших тулзов для реверсинга и декомпильнуть свой проект. Например rabcdasm.

Добавлено через 36 минут
Цитата:
Инициализация статик классов непредсказуема.
Неправда. Очень даже предсказуемо. Инициализация произойдёт в момент первого обращения к типу, т.е. создания переменной, при получении getDefenitionByName и т.п.
Если мы создадим два класса сто статическими полями и кросс ссылками друг на друга то это упадёт в рантайме т.к. во втором сините мы попробуем получить другой тип который ещё не проинитился и вместо него получим null
__________________
:)

Старый 23.02.2012, 15:50
expl вне форума Посмотреть профиль Отправить личное сообщение для expl Найти все сообщения от expl
  № 7  
Ответить с цитированием
expl

блогер
Регистрация: Feb 2006
Сообщений: 1,474
Записей в блоге: 3
Т.е. что, получается если нет кросс-ссылок, а мы содим вот такую весчь:
Код AS3:
public class A
{
    public static var a:int = B.b;
}
public classB
{
    public static var b:int = 10;
}
То а гарантированно получит значение 10?
Вообще да, проверил работает, действительно предсказуемо.

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

Поэтому думал что он вообще как повезёт их инициализирует.
Вобщем, дров наломать можно.

С внутренними классами вообще всё безобразно:
Код AS3:
package {
	import flash.display.Sprite;
	public class Example extends Sprite {
		// Падает со словами "Inner не является конструктором."
		public static var INNER:Inner = new Inner();
		public function Example() {
			trace(INNER);
		}
	}
}
class Inner {}
А так не падает:
Код AS3:
package {
	import flash.display.Sprite;
	public class Example extends Sprite {
		private static var _INNER:Inner;
		public static function get INNER():Inner {
			if (_INNER == null) {
				_INNER = new Inner();
			}
			return _INNER;
		}
		public function Example() {
			trace(INNER);//[object Inner]
		}
	}
}
class Inner {}

Создать новую тему Ответ Часовой пояс GMT +4, время: 02:54.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


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


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