PDA

Просмотр полной версии : как подписать в качестве хендлера события функцию другого объекта?


vitaliy.urazov
22.10.2007, 22:20
subj

Здесь (http://flasher.ru/forum/showthread.php?t=79873) понятно написано как это делать в одном классе.

А как правильно указать то, что обработчик является методом другого класса?
Так или нет?
addEventListener(MouseEvent.CLICK, экземлярДругогоКласса.handler);

И есть ли возможность отлова события в каких либо объектах не подписанных на обработку.
Предположим у меня есть некоторый объект, кот. посылает некое событие и неизвестно существует ли он на данный момент или нет. И есть некоторые объекты, кот. должны обработать это событие, если оно вдруг произойдет, но они не знают создан ли объект или нет, да и не надо им это знать.

Как правильно реализовать такое?

Спасибо.

BlooDHounD
22.10.2007, 23:24
так низя делать. обработчики должны быть приватными.

miramax
23.10.2007, 00:39
1. Можно подписать любой обработчик из области видимости:
addEventListener(MouseEvent.CLICK, экземлярДругогоКласса.handler);
addEventListener(MouseEvent.CLICK, trace);
addEventListener(MouseEvent.CLICK, MyClass.myStaticFunction);
2. Или юзать третий объект, который существует всегда и знает когда существует нужный объект, или заюзать что-то кроме обсервера.

Nirth
23.10.2007, 02:29
Единственное требование, handler должен иметь 1ым аргументом Event, или что нибудь что пройдет как Event (* или Object)

etc
23.10.2007, 10:32
Лучше см. пост #2.

LokiDi L0ck
23.10.2007, 12:58
Если listener сделать публичным.
Main.as3:
package {
import flash.display.Sprite;
import foo.Foo;
import bar.Bar;
import flash.events.MouseEvent;

public class Main extends Sprite
{
public function Main()
{
var f:Foo = new Foo();
var b:Bar = new Bar();

f.addEventListener(MouseEvent.CLICK, b.mouseClickListener);

addChild(f);
addChild(b);
}
}
}

Foo.as3:
package foo
{
import flash.display.Sprite;
import flash.text.TextField;

public class Foo extends Sprite
{
public function Foo()
{
x = 50;
y = 50;

graphics.beginFill(0x009900);
graphics.drawCircle(0, 0, 10);

var text:TextField = new TextField();
text.text = "Foo";
text.x = 10;
text.y = 10;

addChild(text);

}
}
}

Bar.as3:
package bar
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;

public class Bar extends Sprite
{
public function Bar()
{
x = 100;
y = 100;

graphics.beginFill(0x990000);
graphics.drawCircle(0, 0, 10);

var text:TextField = new TextField();
text.text = "Bar";
text.x = 10;
text.y = 10;

addChild(text);
}

public function mouseClickListener(e:MouseEvent):void
{
trace("Вызван Bar.mouseClickListener()");
}
}
}

Если listener сделать приватным, код чуть-чуть поменяется:
В Main.as3:
package {
import flash.display.Sprite;
import foo.Foo;
import bar.Bar;
import flash.events.MouseEvent;

public class Main extends Sprite
{
protected var bClickListener:Function;

public function Main()
{
var f:Foo = new Foo();
var b:Bar = new Bar();

bClickListener = function(e:MouseEvent):void {
trace("MAIN: Foo CLICKED");
b.getClickListener(e)();
};

f.addEventListener(MouseEvent.CLICK, bClickListener);

addChild(f);
addChild(b);
}
}
}

В Bar.as3 - mouseClickListener делается приватным, и добавляется public метод.


public function getClickListener(e:MouseEvent):Function
{
return function():void {
mouseClickListener(e);
};
}


Всё можно сделать красивее, расширив например класс Function через prototype, добавив в него функцию типа Delegate.
Код только для примера, набросал не для реального применения.

etc
23.10.2007, 13:09
Плохой пример.

LokiDi L0ck
23.10.2007, 13:18
Я знаю.

Сэр Макс
23.10.2007, 13:45
Я бы делал так:


public class ClassWithEvents {
public var clickFunction:Function = null;

public function ClassWithEvents() {
this.addEventListener(MouseEvent.CLICK,myClickFunction);
}

private function myClickFunction(event:MouseEvent) {
if (clickFunction != null)
clickFunction(event);
}
}


Или если позволяет структура програмы то так:

public class ClassWithEvents {
public function ClassWithEvents(clickFunction:Function) {
this.addEventListener(MouseEvent.CLICK,clickFunction);
}
}


Соответственно использовать первый вариант можно так:

var a:ClassWithEvents = new ClassWithEvents();
a.clickFunction = somePrivateFunction;


И второй вариант:

var a:ClassWithEvents = new ClassWithEvents(somePrivateFunction);

LokiDi L0ck
23.10.2007, 13:50
А можно просто напросто заюзать event dispatcher =)

Сэр Макс
23.10.2007, 14:03
Для случая автора абсолютно нет смысла. Ему ведь нужно просто запускать чужую функцию при каком-то событии, а используя Event Dispatcher это забитие мухи микроскопом.

LokiDi L0ck
23.10.2007, 14:24
Event Dispatcher это забитие мухи микроскопом

В Main.as3:
f.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void {
b.dispatchEvent(e);
});

Всего три строчки.
Но, верно, это не для этого случая. Поспешил.

2morrowMan
23.10.2007, 14:34
Хватит извращатся! :)
Чел чето накодил там такое, что теперь приходиться что-то придумывать и делать это чере попу! Там явно все можно зделать более... эээ... умнее что ли... :)

LokiDi L0ck
23.10.2007, 15:03
все можно зделать более... эээ... умнее что ли...
2morrowMan, конечно можно. Вышеприведенные примеры не служат юзабельным кодом, а всего лишь демонстрацией, которую можно и нужно привести к логическому концу.
Остальное пусть обдумывает уже сам автор.

2morrowMan
23.10.2007, 16:06
2morrowMan, конечно можно. Вышеприведенные примеры не служат юзабельным кодом, а всего лишь демонстрацией, которую можно и нужно привести к логическому концу.
Остальное пусть обдумывает уже сам автор.
Я имел ввиду код автора(надо было мне это уточнить в моем пред. посте)! Т.е. автор мог бы реализовать свою задумку так чтобы такой проблемы не возникало или чтобы она решалась не через попу, хотя иногда и так можно... если нужно. :)

vitaliy.urazov
23.10.2007, 19:12
Всем большое спасибо за ответы и критику. Картина ясна.

Жизнь сталкивает с проблемами, возникают различные вопросы, кот. приходиться решать. Чтобы не решать их через то место которое упомянул автор предыдущего поста, я и обратился сюда.