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

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

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

Регистрация: Jun 2012
Адрес: Новосибирск
Сообщений: 6,644
Записей в блоге: 4
По умолчанию Оверрайд метода, который использован как 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. Выполнение метода просто тихо отваливалось.

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


Последний раз редактировалось caseyryan; 02.02.2017 в 19:58. Причина: Вопрос решен
Старый 02.02.2017, 14:56
callme вне форума Посмотреть профиль Отправить личное сообщение для callme Найти все сообщения от callme
  № 2  
Ответить с цитированием
callme
 
Аватар для callme

Регистрация: Dec 2014
Сообщений: 312
Можешь компилируемый пример дать?

Старый 02.02.2017, 17:23
KBAC вне форума Посмотреть профиль Отправить личное сообщение для KBAC Найти все сообщения от KBAC
  № 3  
Ответить с цитированием
KBAC
 
Аватар для KBAC

Регистрация: Jan 2006
Адрес: Москва (Нижний Новгород)
Сообщений: 229
Записей в блоге: 1
Отправить сообщение для KBAC с помощью Skype™
А _imageLoader не статический случаем?

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

Старый 02.02.2017, 18:55
caseyryan вне форума Посмотреть профиль Отправить личное сообщение для caseyryan Найти все сообщения от caseyryan
  № 4  
Ответить с цитированием
caseyryan
 
Аватар для caseyryan

Регистрация: Jun 2012
Адрес: Новосибирск
Сообщений: 6,644
Записей в блоге: 4
Цитата:
Сообщение от KBAC Посмотреть сообщение
А _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;
		}
	}
 
}
__________________
Ко мне можно и нужно обращаться на ты)

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

Регистрация: Dec 2014
Сообщений: 312
В 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();
	}
}

Старый 02.02.2017, 19:57
caseyryan вне форума Посмотреть профиль Отправить личное сообщение для caseyryan Найти все сообщения от caseyryan
  № 6  
Ответить с цитированием
caseyryan
 
Аватар для caseyryan

Регистрация: Jun 2012
Адрес: Новосибирск
Сообщений: 6,644
Записей в блоге: 4
callme, да, все верно.
Только что выяснил из-за чего все сломалось.
Там у меня в ImageLoader стоит блок try / catch, в котором вызывается этот колбэк.
И оказалось, что _closeButton в месте где она добавляется == null (как раз в этом методе). Но ошибки не вылетало из-за этого самого try /catch. Выполнение метода просто тихо отваливалось как раз после добавления картинки

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

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

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

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


 


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


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