Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Оверрайд метода, который использован как callback (http://www.flasher.ru/forum/showthread.php?t=213854)

caseyryan 02.02.2017 13:24

Оверрайд метода, который использован как callback
 
Сегодня заметил интересную штуку, о которой раньше даже не задумывался.
Есть у меня один класс, обертка для загрузчика картинок. В нем есть вот такая конструкция
Код AS3:

public function set imagePath(value:String):void {
        if (_imageLoader) return;
        _imagePath = value;
        reset();
        _imageLoader = new ImageLoader(onImageLoaded, _imagePath, onError);
}
public function get imagePath():String {
        return _imagePath;
}
protected function onImageLoaded(image:Bitmap):void {
        _imageLoader                = null;
        _image                                = image;
        _image.smoothing        = true;
        addChild(_image);
        addChild(_closeButton);
        if (_width == 0 || _height == 0) {
                _width                = _image.width;
                _height        = _image.height;
        }
        drawMask();
}

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

override protected function onImageLoaded(image:Bitmap):void {
        super.onImageLoaded(image);
        image.alpha = .3;
        addChild(_nameLabel);
}

Собственно, я всегда полагал, что когда в таком случае происходит вызов (здесь внетри ImageLoader'а) метода класса, то сначала он вызывается в наследнике, а потом, если там есть вызов метода суперкласса, уже передается в суперкласс.
Оказалось нифига подобного. Метод в наследнике не вызывается. То есть в данном случае, как колбэк передается именно жесткая ссылка на метод суперкласса как на объект, и никакие оверрайды уже не учитываются.
Вот такие вот пирожки, товарищи :D
Просто хотел поделиться находкой, которая мне чуть мозг не взорвала)


Решение:
Цитата:

Только что выяснил из-за чего все сломалось.
Там у меня в ImageLoader стоит блок try / catch, в котором вызывается этот колбэк.
И оказалось, что _closeButton в месте где она добавляется == null (как раз в этом методе). Но ошибки не вылетало из-за этого самого try /catch. Выполнение метода просто тихо отваливалось.

Всё, тему можно считать закрытой. Все работает, и дело не в ссылке на метод.

callme 02.02.2017 14:56

Можешь компилируемый пример дать?

KBAC 02.02.2017 17:23

А _imageLoader не статический случаем?

Явно где-то ошибка. Оверрайд должен работать и работает как ожидается.

caseyryan 02.02.2017 18:55

Цитата:

Сообщение от KBAC (Сообщение 1198982)
А _imageLoader не статический случаем?

Явно где-то ошибка. Оверрайд должен работать и работает как ожидается.

Нет, не статический, в каждом классе свой экземпляр
Я тоже думал, что это ошибка. Но много раз проверил. Действительно, из ImageLoader вызывается именно метод суперкласса. 100% вызывается. При этом метод наследника полностью игнорится, ни трейсы ни брейкпоинты в нем не срабатывают. И код, соответственно тоже не выполняется. Я сначала подумал, что может куда-то inline закрался, поэтому валится брейкпоинт, но нет, инлайнов в этом проекте нет.
Убрал всё, оставил в наследнике один трейс. Итог - трейса нет, код в методе суперкласса выполнился.
А вот, чтобы убедиться работают ли в принципе оверрайды я сделал оверрайд другого метода обработчика событий MouseEvent.CLICK, и он отлично вызывается сначала в наследнике, а потом в этом суперклассе

А вот если я помещу ImageLoader наоборот в наследника, и там дам ссыль на этот метод (уже перезаписанный), то метод суперкласса тоже вызовется.


А самом ImageLoader код такой:
Код AS3:

package ru.*****.******.utils {
        import flash.display.Bitmap;
        import flash.display.DisplayObject;
        import flash.display.Loader;
        import flash.events.Event;
        import flash.events.EventDispatcher;
        import flash.events.IOErrorEvent;
        import flash.events.ProgressEvent;
        import flash.net.URLRequest;
        import flash.system.LoaderContext;
 
        public class ImageLoader extends EventDispatcher {
 
                private var _loader:                Loader                = null;
                private var _callback:                Function        = null;
                private var _errorCallback:        Function        = null;
                private var _additParams:        Array                = null;
 
                public function ImageLoader(callback:Function, imageUrl:String, errorCallback:Function = null, additParams:Array = null) {
                        _additParams                = additParams;
                        _callback                = callback;
                        _errorCallback        = errorCallback;
                        _loader                        = new Loader();
                        _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
                        _loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
                        _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
                        var context:LoaderContext = new LoaderContext(true);
                        try {
                                _loader.load(new URLRequest(imageUrl), context);
                        } catch (e:Error) {
                                if (_errorCallback != null) {
                                        _errorCallback.call();
                                }
                                trace(e.getStackTrace());
                                removeListeners();
                        }
                }
 
                private function onProgress(e:ProgressEvent):void {
                        var percent:int = int(e.bytesLoaded / e.bytesTotal * 100);
                }
 
                private function onIOError(e:IOErrorEvent):void {
 
                        if (_errorCallback != null) {
                                _errorCallback.call();
                        }
                        removeListeners();
                }
 
                private function onComplete(e:Event):void {
 
                        try {
                                var displayObject:DisplayObject        = e.target.content as DisplayObject;
                                if (_callback != null) {
                                        if (_additParams != null) {
                                                _callback.call(null, displayObject, _additParams);
                                        } else {
                                                _callback.call(null, displayObject);
                                        }
                                        _callback        = null;
                                }
                        } catch (e:Error) { }
                        removeListeners();
 
                }
                private function removeListeners():void {
                        _loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete);
                        _loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onIOError);
                        _loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress);
                        _loader                = null;
                        _callback        = null;
                        _errorCallback        = null;
                }
                public function dispose():void {
 
 
                        removeListeners();
                        if (_loader) {
                                try {
                                        _loader.close();
                                } catch (e:Error) {}
                                _loader = null;
                        }
                        _callback                = null;
                        _errorCallback        = null;
                        _additParams        = null;
                }
        }
 
}


callme 02.02.2017 19:09

В output выводится b.

Код AS3:

package
{
        import flash.display.Sprite;
 
        public class Main extends Sprite
        {
                public function Main()
                {
                        var b:B = new B();
                        b.func2();
                }
        }
}
 
 
class A
{
        public function func1():void
        {
                trace('a');
        }
 
        public function func2():void
        {
                new C(func1);
        }
}
 
class B extends A
{
        override public function func1():void
        {
                trace('b');
        }
}
 
class C
{
        public function C(f:Function)
        {
                f();
        }
}


caseyryan 02.02.2017 19:57

callme, да, все верно.
Только что выяснил из-за чего все сломалось.
Там у меня в ImageLoader стоит блок try / catch, в котором вызывается этот колбэк.
И оказалось, что _closeButton в месте где она добавляется == null (как раз в этом методе). Но ошибки не вылетало из-за этого самого try /catch. Выполнение метода просто тихо отваливалось как раз после добавления картинки

Всё, тему можно считать закрытой. Все работает, и дело не в ссылке на метод.


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

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