PDA

Просмотр полной версии : Преобразование типов на уровне класса


Halfist
21.02.2012, 18:28
Можно ли сделать объект (после его создания) экземпляром другого класса (для того, чтобы унаследовать его свойства)? Если да, то как это сделать? Если нет, есть ли какой-то другой способ?

Другими словами - преобразование типов на уровне класса.

Заранее спасибо за ответ!

СлаваRa
21.02.2012, 18:35
если я правильно понял, то вам, наверное, вот это надо Делегирование (http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BB%D0%B5%D0%B3%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0% B2%D0%B0%D0%BD%D0%B8%D0%B5)) 2 пункт смотрите.

Halfist
21.02.2012, 19:05
Объясняю подробней.


package classes
{
public class myClass extends MovieClip
{
public var test:String = "Hello!";
}
}



import classes.*;

var A = new MovieClip();
A.height = 100;
var B = new myClass();
A = B;
result_tf.appendText(A.test + "\n");
result_tf.appendText(A.height + "\n");


Как видно из кода, объект A типа MovieClip присваивается объекту B типа myClass. Хотелось получить доступ как к стандартным свойствам MovieClip (тобишь x, y, height, width и т.д.), так и к собственноручно написанным (в данном случае test). Вместо этого, после присвоения A = B, объект A "забывает / теряет" свои родные свойства MovieClip и видит только test. На экране видно Hello! и 0 вместо Hello! и 100.

Делается это для того, чтобы добавить в объект свои свойства и методы.

-De-
21.02.2012, 19:13
После присваивания A = B; A - уже ДРУГОЙ мувик и у него может быть другая высота. Ваш кэп.

Johny_86
21.02.2012, 19:25
У тебя А и В (кстати, почему без типа) на самом деле не объекты, а ссылки на объекты в памяти. Есть объект мувик, которому ты присвоил высоту 100. на него ссылается переменная А. Есть объект типа myClass, который ты просто создал. Ему никакую высоту ты не ставил и у него она равна 0. Потом ты берешь и говоришь, что теперь ссылка А равна ссылке В - и они оба ссылаются на объект типа myClass. А у первого объекта, как была высота 100, так она и есть! Просто к нему теперь нет доступа.

Deimos747
21.02.2012, 19:26
Halfist, а что вам мешает сделать так?

import classes.*;

var A: myClass = new myClass();
A.height = 100;
result_tf.appendText(A.test + "\n");
result_tf.appendText(A.height + "\n");

Halfist
21.02.2012, 19:30
import classes.*;

var A = new MovieClip();
A.height = 100;
var B = new myClass();
B.height = 999;
A = B;
result_tf.appendText(A.test + "\n");
result_tf.appendText(A.height + "\n");


Если бы свойство height (со своим значением) унаследовалось, а не заменилось, в текстовое поле вывелось бы 999. На самом же деле - 0.

СлаваRa
21.02.2012, 19:35
Если бы свойство height (со своим значением) унаследовалось, а не заменилось, в текстовое поле вывелось бы 999. На самом же деле - 0.

откуда вы такое взяли?

-De-
21.02.2012, 19:35
Если клип пуст, то ему нельзя выставить height. Это скорее метод, чем св-во.
var A = new MovieClip();
A.height = 100;
result_tf.appendText(A.height + "\n");//0, лол

Halfist
21.02.2012, 19:36
Всё дело в том, что у меня есть "фабрика", которая создаёт объекты (которые по-умолчанию, естественно, extends MovieClip, не могу же я в фабрике приказать объектам extends myClass). Вот к этим объектам потом вручную нужно "допилить" свойства, собственноручно написанные в классе myClass.

Johny_86
21.02.2012, 19:39
var a:MovieClip = new MovieClip();
a.height = 100;

var b:MyClass = new MyClass();
b.height = 999;

a = b;
trace(a.height) выведет 999!

Gaen
21.02.2012, 20:40
Вы, видимо, хотите руками перестроить цепочку прототипов, как в яваскпипте. Увы, в AS3 такое не катит. Используйте паттерн Decorator.

carrotoff
21.02.2012, 21:12
Всё дело в том, что у меня есть "фабрика", которая создаёт объекты (которые по-умолчанию, естественно, extends MovieClip, не могу же я в фабрике приказать объектам extends myClass). Вот к этим объектам потом вручную нужно "допилить" свойства, собственноручно написанные в классе myClass.

Что-то слишком на кашу похоже. Почему "естественно, extends MovieClip, не могу же я в фабрике приказать объектам extends myClass" ?

Может, вы подробней распишите задачу?
Обычно за наращивание функционала отвечает Декоратор (http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BA%D0%BE%D1%80%D0%B0%D1%82%D0%BE%D1%80_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0 %B2%D0%B0%D0%BD%D0%B8%D1%8F))(как уже было замечено выше) или фасад (http://ru.wikipedia.org/wiki/%D0%A4%D0%B0%D1%81%D0%B0%D0%B4_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1 %8F)).

Halfist
21.02.2012, 23:43
Есть, значит, у меня в библиотеке >200 фрагментов ролика, каждый из которых экспортирован для ActionScript. Класс, обрабатывающий каждый из них, я не редактировал, поскольку тогда пришлось бы создавать >200 *.as файлов. Через JSON в виде строки приходит имя класса, экземпляр которого нужно создать.

Есть следующий класс-абстракция, который наследует MovieClip:

package classes
{
import flash.display.MovieClip;
import flash.display.DisplayObject;
import flash.utils.getDefinitionByName;

public class item extends MovieClip
{
public var classInner:DisplayObject;
public var f1:String;
/* фабрика */
public function factory(strClassName:String):void
{
var className:Class = getDefinitionByName(strClassName) as Class;
this.classInner = new className();
}
}
}


А также более конкретный класс, который наследует item:

package classes
{
public class bodyClass extends item
{
public var f2:String;
public var f3:String;
public var f4:String;
}
}


В коде внутри *.fla файла происходит следующее:

var bodyLayer:Sprite = new Sprite(); addChild(bodyLayer);
var myRequest:URLRequest = new URLRequest("...");
var myLoader = new URLLoader();
myLoader.addEventListener(Event.COMPLETE, onload);
myLoader.load(myRequest);
var bodyNum:int = 0;

function onload(evt:Event):void
{
var myData:Object = JSON.decode(myLoader.data);
var key:Object;
for (key in myData.bodies)
{
var body = new bodyClass();
body.factory(myData.bodies[key].className);
var bodies:Array = [];
bodies[myData.bodies[key].className] = [];
bodies[myData.bodies[key].className][bodyNum] = body;
bodies[myData.bodies[key].className][bodyNum].classInner.f1 = "str1";
bodies[myData.bodies[key].className][bodyNum].classInner.f2 = "str2";
bodies[myData.bodies[key].className][bodyNum].classInner.f3 = "str3";
bodies[myData.bodies[key].className][bodyNum].classInner.f4 = "str4";
bodies[myData.bodies[key].className][bodyNum].classInner.height = 100;
bodies[myData.bodies[key].className][bodyNum].classInner.width = 100;
bodies[myData.bodies[key].className][bodyNum].classInner.addEventListener(MouseEvent.MOUSE_OVER,bodyOnMouseOver);
bodyLayer.addChildAt(bodies[myData.bodies[key].className][bodyNum].classInner, 0);
bodyNum++;
}
}


Мне нужно, чтобы у bodies[myData.bodies[key].className][bodyNum].classInner (объект, который является свойством класса item) были все свойства MovieClip, item и bodyClass. На самом же деле, у него есть только свойства и методы MovieClip, поскольку "В библиотеке >200 фрагментов ролика, каждый из которых экспортирован для ActionScript. Класс, обрабатывающий каждый из них, я не редактировал, а он extends MovieClip".

-De-
22.02.2012, 00:19
Слишком хитро, сами себя обманете. Зачем такое было городить вообще?

Можно выделить эти >200 фрагментов в библиотеке и поставить им базовым классом bodyClass, по-моему один и тот же куче клипов там можно поставить (тогда таки будут все св-ва).

У вас будет дублирование - bodies[myData.bodies[key].className][bodyNum] имеет поля f1, f2, f3, f4 и сам он является зачем-то мувиком и вы хотите, чтоб bodies[myData.bodies[key].className][bodyNum].classInner тоже имел эти поля (и bodies[myData.bodies[key].className][bodyNum].classInner.classInner).
Что-то надо убрать.

По-моему лучше всего, чтоб item не расширял MovieClip и чтоб не надо было classInner быть наследником bodyClass =) Данные брать из bodies[myData.bodies[key].className][bodyNum] (который bodyClass).
Или bodies[myData.bodies[key].className][bodyNum] - должен быть классом, которому таки поставлен bodyClass базовым классом, который создаст поправленная (чтоб она такое могла делать) фабрика.

И массив bodies - используется не стандартно и запутывает тем, что он массив, он у вас как Object используется.
Ещё загадочен массив bodies[myData.bodies[key].className] - в нём всегда один элемент будет?

PS: внутри .fla кода не должно быть, особенно если он по сложности как тот, что выше, используйте document class.

Halfist
22.02.2012, 00:25
Можно выделить эти >200 фрагментов в библиотеке и поставить им базовым классом bodyClass, по-моему один и тот же куче клипов там можно поставить (тогда таки будут все св-ва).

Нельзя, поскольку из JSON может прийти одно из >200 имён классов, экземпляр которого нужно создать (каждый внешне выглядит по-разному).

Gaen
22.02.2012, 00:28
-De-, снимаю шляпу, у меня на всей этой перелинковке мозг сломался :)

Halfist
22.02.2012, 00:36
Массив нужен для того, чтобы "всунуть" туда несколько объектов, т.к. из JSON приходит не одна запись, а также знать, к какому конкретно объекту в данный момент идёт обращение. Они разные, поскольку на каждой итерации цикла bodyNum++.

-De-
22.02.2012, 00:38
У меня давно сдох CS4, потому плохо помню и проверить не могу, может и нельзя )
Но символу можно поставить класс (который один из >200 имён и я так понял они все тупо мувиклипы). И можно поставить базовый класс. Который у всех этих > 200 имён будет один bodyClass.

PS: у вас не будет в массиве bodies[myData.bodies[key].className] более одного элемента т.к. он каждый раз создаст новый массив на месте предыдущего. Наверное это баг и
вместо
bodies[myData.bodies[key].className] = [];
надо
if(null == bodies[myData.bodies[key].className])
bodies[myData.bodies[key].className] = [];
И может там стоит в этот массив тупо push делать, а не тянуть bodyNum?

Halfist
22.02.2012, 00:44
Класс для каждого фрагмента ролика указан (их >200).
А вот базовый класс нельзя изменить, поскольку "Указанный базовый класс является собственным классом и будет определён в проигрывателе во время выполнения. Он не может быть изменён.". Его значение, конечно же, flash.display.MovieClip.