PDA

Просмотр полной версии : Экземпляр, созданный при объявлении статического свойства не видит других классов


Ромастый
06.08.2007, 19:45
Столкнулся со следующей штукой.
class MyClass {
static var ref = new MyClass("from class MyClass: ");
function MyClass(from) {
var from=from? from : "from outside:"
trace(from+" "+mx.events.EventDispatcher);
}
}
во fla:
myClass = new MyClass();
//from class MyClass: undefined
//from outside: [type Function]
При создании экземпляра класса через объявление статического свойства класса экземпляр не видит других пользовательских классов.
(С тем же успехом вместо mx.events.EventDispatcher можно написать mx.utils.Delegate)
Однако
class MyOtherClass extends MyClass {
static var ref = new MyOtherClass("from class MyOtherClass extends MyClass: ");
function MyOtherClass(from) {
super(from)
}
}
myOtherClass = new MyOtherClass();
//from class MyClass: [type Function]
//from class MyOtherClass extends MyClass: [type Function]
//from outside: [type Function]
В этом случае все работает, то есть в дочернем классе при создании экземпляра через стат-свойство мы можем обращаться к методам и свойствам других классов.

Кроме того, если в MyClass заменить EventDispatcher на какой-либо из документированных классов (XML или скажем BitmapData) - тоже все нормально работает.
В чем тут дело? Особый порядок инициализации классов?

etc
06.08.2007, 20:04
Для начала неплохо было бы все-таки написать import.

Ромастый
06.08.2007, 20:12
Для начала неплохо было бы все-таки написать import.

А без разницы. В AS2 директива import используется только для сокращения полных имен классов.
Но даже если написать import
import mx.events.EventDispatcher;
class MyClass {
static var ref = new MyClass("from class MyClass: ");
function MyClass(from) {
var from=from? from : "from outside:"
trace(from+" "+EventDispatcher);
}
}
флэш все равно выдаст from class MyClass: undefined
Ессно проверял, перед тем как постить.

etc
06.08.2007, 20:19
Да-да-да. Заплатка:

import mx.events.EventDispatcher;
class MyClass {
private static var __dummy:EventDispatcher = EventDispatcher;
public static var instance:Object = new MyClass("static");
public function MyClass(str:String) {
trace(str+':'+EventDispatcher);
}
}

Что и как расскажу потом, ибо домой надо бежать.

Ромастый
06.08.2007, 20:30
Да-да-да. Заплатка
Мда, не сообразил... :confused:
Спасиб! :)

P.S. Раз речь идет о заплатке, как я понял - очередные грабли?

Kikasso
06.08.2007, 21:17
У меня FDT вообще не дает объявлять непростые типы вне функций.
Грабли в том, что например вы пишете
static var ref = new MyClass("from class MyClass: ");
а попробуйте написать так:
var ref = new MyClass("from class MyClass: ");
Знайте, что ref во втором случае тоже будет статичным.

Ромастый
06.08.2007, 21:56
а попробуйте написать так:
var ref = new MyClass("from class MyClass: ");
Знайте, что ref во втором случае тоже будет статичным.
Очень спорно. Поясню:
1.Если так писать при объявлении свойства - будет белиберда.
2.Если ref объявить как static, а значение присваивать в конструкторе, то оно ессно будет статическим, вот только каждый раз это будет новый объект.:away:
3.Единственно что в таком варианте сработает - это написать отдельный метод, который создает экземпляр MyClass и делает ref ссылкой на него, после чего вызывать это метод единожды.
А вопрос был собственно о создании экземпляра в объявлении свойств.
__etc дал ответ в точку.

etc
06.08.2007, 22:56
Вообще говоря, лучше применять паттерн синглтон и не работать со статической ссылкой напрямую.

А заплатка… да, заплатка, потому что компилятор инициализирует все, кроме тел методов, в итоге он просто не догадывается, что EventDispatcher нужно инициализировать раньше MyClass.

Ромастый
07.08.2007, 01:57
Вот собсно необходимость такой заплатки и интересовала - почему флэш в данном случае прекрасно видит документированные классы (вроде той же BitmadDatы), но не инициализирует пользовательские?
Напрашивается только один ответ.

Что касается синглтона... Если интересно, могу рассказать.
Есть дерево классов с бесконечным количеством дочерних классов (теоретически, практически же 5-10 уровней наследования, но сути не меняет).
Статические(!) свойства любого из классов могут меняться по событию,
И все экземпляры этого класса, а также экземпляры расширяющих этот класс, должны тут же отреагировать.
Собственно, синглтон я сразу же и использовал - подписывать все экземпляры дочернего класса на его синглтон, а синглтон дочернего в свою очередь на синглтон родительского.
Вот только одна проблема: при расширении синглтона метод getInstance в дочернем классе каждый раз надо оверрайдить. Учитывая 5-10 уровней наследования и около 200-300 классов, картинка получается жестковата, даже несмотря на то, что as-файлы будут генериться каким-нить ming'ом... В общем захотелось схалявить, и сделать это одной строчкой - через объявление статического свойства и присвоение ему экземпляра.
Если есть другие решения - буду рад узнать :)

Kikasso
07.08.2007, 02:34
Я собственно другой глюк имел в виду.
as

class Test{
public static var arr:Array = [];
public var arr2:Array = [];
public var id:String;
public function Test( id:String ){
arr.push( this );
arr2.push(this);
this.id = id;
}
public function toString():String{
return 'Test '+ id;
}
}

fla

import Test;
var t1:Test = new Test('t1');
var t2:Test = new Test('t2');
trace( Test.arr );
trace('----------');
trace( t1.arr2 );
trace('----------');
trace( t2.arr2 );
trace('----------');

trace

Test t1,Test t2
----------
Test t1,Test t2
----------
Test t1,Test t2
----------

Попытка оттрейсить Test.arr2 вызовет ошибку - то есть свойство как бы не статичное.
А по вашему вопросу - можно так:
as
class Test{
public static var ref:Test = Test.createRef();
public var id:String;
public static function createRef():Test{
trace('ссылка создана');
return new Test('etalon');
}
public function Test( id:String ){
this.id = id;
}
public function toString():String{
return 'Test '+ id;
}
}
flaimport Test;
var t1:Test = new Test('t1');
trace( Test.ref );
var t2:Test = new Test('t2');
trace( Test.ref );
P.S. что такое синглтон, сорри, не знаю. Гуглить лень.

Ромастый
07.08.2007, 02:59
Я собственно другой глюк имел в виду.
Интересная козява =))
Но что-то мне подсказывает, что такое только с массивами происходит, а с другими наследниками Object'a не наблюдается. Буду иметь ввиду, спасиб.
Впрочем, в теме поста речь шла действительно о другом.

P.S. что такое синглтон, сорри, не знаю. Гуглить лень.
Синглтон - это мегаштука. Я бы сказал - мегаполезнаяхрень, когда нужен единичный экземпляр. Например при открытии сокета.
Но когда наследуешь от такой - приходится оверрайдить. Разок-другой это ничего, а вот раз через 10 начнешь смущаться, через 20 сомневаться, через 50 - надеяться, что сможешь найти меньшее зло.

etc
07.08.2007, 09:43
Kikasso, это совсем не в тему.

Ромастый, дело в том, что встроенные классы всегда инициализированы. EventDispatcher не является встроенным.

А 5—10 уровней наследования — чума. Не представляю себе такой ситуации, где оно действительно нужно.

Ромастый
07.08.2007, 13:02
Ну от чего ж? В mx компонентах, к примеру, количество уровней наследования достигает 4-5, а порой и 8. :)

etc
07.08.2007, 13:19
Неправильно это. Никто и не говорит, что mx.* — хорошие.