| « JavaFX: для тех, кто в Питере | Поздравления » |
Аспекты наследования во Flex
Если кто-то занимался исследованием кода компонент Flex-фрэймворка, мог заметить некоторые особенности реализации метода createChildren() практически во всех классах:
- override protected function createChildren():void
- {
- super.createChildren();
- if (!titleBar)
- {
- titleBar = new UIComponent();
- ...
- rawChildren.addChild(titleBar);
- }
- if (!titleTextField)
- {
- titleTextField = new UITextField();
- ...
- titleBar.addChild(titleTextField);
- }
- ...
- }
Примерно в таком духе.
Не очень понятно, зачем проверять существование создаваемых GUI-элементов, если метод createChildren() вызывается из конструктора, и именно в нем создаются контролы? Думаю, что многие знают, для остальных смысл объясняется ниже.
Предположим мы хотим создать вариант класса mx.controls.Alert, который может отображать текст с HTML-форматированием. Задача может показаться сложной, но описанное выше дизайнерское решение создателей Flex-фрэймворка существенно облегчает нам задачу, делая ее очень легкой.
Рассмотрим место в коде mx.controls.Alert, которое нас интересует:
- override protected function createChildren():void
- {
- super.createChildren();
- ...
- if (!alertForm)
- {
- alertForm = new AlertForm();
- alertForm.styleName = this;
- addChild(alertForm);
- }
- }
Именно поле alertForm содержит экземпляр класса mx.controls.alertClasses.AlertForm, в котором и находится наше текстовое поле. Идея простая: нам надо создать свой класс AlertForm и попробовать создать его экземпляр в методе createChildren() класса com.riapriority.controls.HTMLAlert, который мы хотим получить.
Логично предположить, что наш класс com.riapriority.controls.HTMLAlertForm будет наследоваться от оригинального AlertForm. И тогда благодаря проверке на существование alertForm мы преспокойно можем написать наш метод createChildren():
- override protected function createChildren():void
- {
- alertForm = new HTMLAlertForm();
- alertForm.styleName = this;
- addChild(alertForm);
- super.createChildren();
- }
Итак, идея понятна. Если же мы хотим дать возможность и другим проделывать ту же операцию, то лучше написать так:
- override protected function createChildren():void
- {
- if (!alertForm)
- {
- alertForm = new HTMLAlertForm();
- alertForm.styleName = this;
- addChild(alertForm);
- }
- super.createChildren();
- }
То же самое проделываем в классе com.riapriority.controls.HTMLAlertForm:
- override protected function createChildren():void
- {
- if (!textField)
- {
- textField = new UITextField();
- textField.styleName = this;
- textField.htmlText = Alert(parent).text;
- textField.multiline = true;
- textField.wordWrap = true;
- textField.selectable = true;
- addChild(textField);
- }
- super.createChildren();
- }
Единственная проблема в том, что статический метод show() класса mx.controls.Alert придется продублировать в нашем HTMLAlert: статические методы не наследуются. Итоговый класс com.riapriority.controls.HTMLAlert:
- package com.riapriority.controls
- {
- import flash.display.Sprite;
- import mx.controls.Alert;
- import mx.core.Application;
- import mx.core.mx_internal;
- import mx.events.CloseEvent;
- import mx.managers.PopUpManager;
- use namespace mx_internal;
- public class HTMLAlert extends Alert
- {
- public function HTMLAlert()
- {
- super();
- }
- override protected function createChildren():void
- {
- if (!alertForm)
- {
- alertForm = new HTMLAlertForm();
- alertForm.styleName = this;
- addChild(alertForm);
- }
- super.createChildren();
- }
- public static function show(text:String = "",
- title:String = "",
- flags:uint = 0x4 /* Alert.OK */,
- parent:Sprite = null,
- closeHandler:Function = null,
- iconClass:Class = null,
- defaultButtonFlag:uint = 0x4 /* Alert.OK */):Alert
- {
- var modal:Boolean = (flags & Alert.NONMODAL) ? false : true;
- if (!parent)
- parent = Sprite(Application.application);
- var alert:Alert = new HTMLAlert();
- if (flags & Alert.OK||
- flags & Alert.CANCEL ||
- flags & Alert.YES ||
- flags & Alert.NO)
- {
- alert.buttonFlags = flags;
- }
- if (defaultButtonFlag == Alert.OK ||
- defaultButtonFlag == Alert.CANCEL ||
- defaultButtonFlag == Alert.YES ||
- defaultButtonFlag == Alert.NO)
- {
- alert.defaultButtonFlag = defaultButtonFlag;
- }
- alert.text = text;
- alert.title = title;
- alert.iconClass = iconClass;
- if (closeHandler != null)
- alert.addEventListener(CloseEvent.CLOSE, closeHandler);
- PopUpManager.addPopUp(alert, parent, modal);
- alert.setActualSize(alert.getExplicitOrMeasuredWidth(),
- alert.getExplicitOrMeasuredHeight());
- return alert;
- }
- }
- }
Итоговый класс com.riapriority.controls.HTMLAlertForm:
- package com.riapriority.controls
- {
- import mx.controls.Alert;
- import mx.controls.alertClasses.AlertForm;
- import mx.core.UITextField;
- import mx.core.mx_internal;
- use namespace mx_internal;
- public class HTMLAlertForm extends AlertForm
- {
- override protected function createChildren():void
- {
- if (!textField)
- {
- textField = new UITextField();
- textField.styleName = this;
- textField.htmlText = Alert(parent).text;
- textField.multiline = true;
- textField.wordWrap = true;
- textField.selectable = true;
- addChild(textField);
- }
- super.createChildren();
- }
- }
- }
Использование стандартное - HTMLAlert.show (...). Но в тексте теперь можно задавать HTML-форматирование.
Не так много кода, не правда ли?
Трекбек адрес этой записи
URL трекбека (щелкните правой кнопкой мыши и скопируйте ссылку)
4 комментариев
ИМХО лучше всего выкладывать примеры в SWF формате и View Source по правой клавише.
У меня есть вопрос, не запуская код у себя.
Переменная alertForm в классе Alert объявлена как:
mx_internal var alertForm:AlertForm
Разве мы можем переопределять тип этой переменной на HTMLAlertForm в классе наследнике HTMLAlert?
even I don't understand your language, I do with your code.
I was nearly right but you made the missing hint.
greats