Почему Flex позволяет мне рассматривать класс как объект - PullRequest
1 голос
/ 15 ноября 2008

Этот код является грубым, поскольку он добавляет класс в массив, а затем пытается извлечь его и манипулировать им, как если бы он был объектом.

private function fail(event:Event):void
{
    var myObj:MyClass;
    var a:ArrayCollection = new ArrayCollection();
    var x:MyClass;
    var y:MyClass;

    myObj = new MyClass;
    a.addItem(myObj);
    a.addItem(MyClass);  // !!BAD!!

    x = a[0];
    y = a[1];
}

Когда я сделал это случайно, мне потребовалось целую вечность, чтобы увидеть, что я сделал неправильно. Отчасти потому, что сообщение об ошибке не говорило мне ничего, что я мог понять:

TypeError: Error #1034: Type Coercion failed: cannot convert com.ibm.ITest::MyClass$ to com.ibm.ITest.MyClass.
    at ITest/fail()[C:\work_simple01\ITest\src\ITest.mxml:51]
    at ITest/___ITest_Button5_click()[C:\work_simple01\ITest\src\ITest.mxml:61]

Так что мой вопрос, почему линия помечена !! ПЛОХОЙ !! выше даже разрешено? Я ожидал бы ошибку времени компиляции здесь. Так как это компилируется, должно быть какое-то использование для этого, о котором я не знаю. Что это?

Ответы [ 4 ]

8 голосов
/ 02 декабря 2008

Вопрос кажется мне эквивалентным: «Почему я могу использовать класс в качестве значения?» Это хороший вопрос.

Есть две основные вещи, которые вы можете сделать с классом в ActionScript; вы можете создать экземпляр этого, и вы можете получить доступ к статическим свойствам этого. (Хорошо, есть и другие вещи, но они очевидны.) Создание класса, вероятно, является наиболее уместным использованием класса в качестве значения; Класс - это его собственная фабрика , подобная тем, которые вы явно сделали бы в C ++ или Java.

Вот пример из маленькой игры в тетрис, которую я писал в качестве упражнения. У меня было два класса, Брик и SceneBrick. Кирпич - это игровой кирпич, который падает и накапливается. SceneBrick - это кирпичик, просто нарисованный как рамка игровой площадки.

Однако я использовал одну функцию, чтобы нарисовать их оба, не обращаясь ни к одному из типов внутри функции:

function drawBricks(xs:Array, ys:Array, brickType:Class){
 xs.map(function(o,i,a){
  var brick = new brickType();
  // etc.
 });    
}

И я мог бы использовать это так:

drawBricks([0,1,2,3], [4,4,4,4], Brick); // draw a long piece
drawBricks(times(0, 21), countFrom(0, 21), SceneBrick); // draw a big vertical "wall"

В ActionScript вы можете передавать класс как значение и использовать его для создания экземпляра этого класса. В таком языке, как Java или C ++, вам придется либо использовать его в качестве параметра для универсального класса, либо определить фабричные классы с некоторым общим супертипом, чтобы сделать это.

7 голосов
/ 15 ноября 2008

Я предполагаю, что исключение произошло в последней строке вашего образца, а не ошибка, которую вы отметили как "ПЛОХОЙ".

В массив добавлен объект, представляющий класс MyClass, а не экземпляр MyClass.

Возможность проверять классы во время выполнения - это мощная функция, которая является основой функций отражения в .NET и Java. Эти функции часто используются для поддержки шаблонов расширяемости или реализации платформ сериализации.

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

1 голос
/ 02 декабря 2008

Кажется, что во Flex коллекции не указывают тип значений, которые они должны содержать.

var a:ArrayCollection = new ArrayCollection();

Так что для меня логично, что компилятор не проверяет типы значений, которые вы к нему добавляете. Тогда назначение переменных из элементов коллекции может быть проверено только во время выполнения, так как компилятор не имеет информации.

Что касается классов, являющихся объектами (и отвечающими на сообщения), очень удобно создавать все виды инструментов отладки / проверки / отражения.

0 голосов
/ 15 ноября 2008

Приятной особенностью позднего связывания (и динамических языков) является то, что он обеспечивает гораздо большую гибкость в реализации. Недостатком является то, что язык не защищает вас от некоторых простых ошибок, которые мешают раннему связыванию и строгой типизации. Лично я бы хотел использовать TDD (разработку через тестирование), чтобы предотвратить появление подобных ошибок в вашем коде.

...