Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   странное поведение as (http://www.flasher.ru/forum/showthread.php?t=171323)

goldlider 13.11.2011 23:40

странное поведение as
 
Доброго времени суток. Возникла проблема с пониманием работы оператора as. Читал help и Мука и данный faq, но честно говоря, не понял.
На примере данного кода:

Почему же вызывается метод destroy класса MapObject? Ведь разные типы имеют переменная _layerMain и класс MapObject.
Код AS3:

package
{
        public class GameMap extends Sprite
        {
                private var _layerMain:Sprite;
 
                public function GameMap()
                {
                        _layerMain = new Sprite();
                        addChild(_layerMain);
                }
 
                public function clear():void
                {
                        if (_layerMain.getChildAt(0) is MapObject)
                        {
                                /* destroy - это пользовательский метод класса MapObject
                                          class MapObject extends Sprite */

                                  (_layerMain.getChildAt(0) as MapObject).destroy();
                        }
                }
        }
}


-De- 13.11.2011 23:48

_layerMain - имеет один тип, а _layerMain.getChildAt(0) - это совершенно другой обьект, который может иметь (и, в вашем случае, имеет) другой тип.

goldlider 13.11.2011 23:58

Цитата:

Сообщение от -De- (Сообщение 1045847)
_layerMain - имеет один тип, а _layerMain.getChildAt(0) - это совершенно другой обьект, который может иметь (и, в вашем случае, имеет) другой тип.

Мне не важно что находится внутри _layerMain. Важно как он преобразует в тип MapObject. Хорошо приведу другой код

Код AS3:

private var _cells:Array
_cells[brush.tileY][brush.tileX] as MapObject

Почему же тип переменной _cells переводится в тип MapObject.

t4arty 14.11.2011 00:32

что у Вас находится по адресу: _cells[brush.tileY][brush.tileX] и будет восприниматься как MapObject

-De- 14.11.2011 00:39

Тип переменной _cells не переводится в этом коде в MapObject. Чтобы таки попробовать перевести и убедиться, что Array не переводится в MapObject, надо писать
Код AS3:

_cells as MapObject

В предыдущем примере это будет
Код AS3:

_layerMain as MapObject

Вы не видите отличия между _cells и _cells[brush.tileY][brush.tileX]?

goldlider 14.11.2011 00:42

приведите пример я че то не догоняю.

GBee 14.11.2011 01:01

у вас на спрайте _layerMain лежит объект MapObject (от DisplayObject).

у вас в массиве _cells "лежит по адресу" [brush.tileY][brush.tileX] объект MapObject (от DisplayObject).

Ookami 14.11.2011 01:31

_cells - сам массив
_cells[brush.tileY][brush.tileX] - конкретный элемент массива

goldlider 14.11.2011 12:40

Цитата:

Сообщение от GBee (Сообщение 1045862)
у вас на спрайте _layerMain лежит объект MapObject (от DisplayObject).

у вас в массиве _cells "лежит по адресу" [brush.tileY][brush.tileX] объект MapObject (от DisplayObject).

Откуда такое предположение, что в _cells[brush.tileY][brush.tileX] лежит объект MapObject?

Аналогичный пример:


Код AS3:

package
{       
        import flash.display.Sprite;
 
        public class A extends Sprite // Основной класс приложения
        {
                public function A()
                {       
                        var msg:B = new B();
                        (msg as C).helloBoys;
                }
        }
}

Код AS3:

package
{       
        public class B
        {
                public function B()
                {
 
                }
 
                function helloGirls():void
                {
                        trace("Come on babes");
                }
        }
}

Код AS3:

package
{       
        public class С
        {
                public function C()
                {
 
                }
 
                function helloBoys():void
                {
                        trace("Come on boys");
                }
        }
}

Почему в данном случае объект msg не приводится к типу C? Ведь данный пример яв-ся аналогом предыдущего. Здесь msg яв-ся аналогом _layerMain оба имеют разные типы и приводятся к типу не соответствующего иерархии наследования.

КорДум 14.11.2011 12:44

Цитата:

Почему в данном случае объект msg не приводится к типу C?
Потому что это приведение к типу. А не конвертирование в тип.

i.o. 14.11.2011 12:45

http://help.adobe.com/ru_RU/FlashPla...rators.html#as

КорДум 14.11.2011 12:47

(msg as C) даст null. А у null нет такого поля - helloBoys

GBee 14.11.2011 12:52

Вы серьезно? Такие вопросы исчезают после первой нормальной книги об ООП или даже статье.

Цитата:

Откуда такое предположение, что в _cells[brush.tileY][brush.tileX] лежит объект MapObject?
Цитата:

Код AS3:

private var _cells:Array
_cells[brush.tileY][brush.tileX] as MapObject


_cells массив, в него что угодно можно пихнуть, а судя по представленному ВАМИ коду в него пихнули MapObject

Цитата:

Почему в данном случае объект msg не приводится к типу C? Ведь данный пример яв-ся аналогом предыдущего. Здесь msg яв-ся аналогом _layerMain оба имеют разные типы и приводятся к типу не соответствующие иерархии наследования.
Прочитайте что-нить об ООП, потом приложите руку к лицу.

Wolsh 14.11.2011 13:00

1.
Цитата:

Откуда такое предположение
потому что с Ваших же слов
Цитата:

Почему же вызывается метод destroy класса MapObject?
2.
Цитата:

Почему в данном случае объект msg не приводится к типу C? Ведь данный пример яв-ся аналогом предыдущего.
Ничего подобного. Не путайте Класс объекта с Типом переменной. В случае с массивом возвращается ТИП Object, но сам возвращаемый объект имеет тот Класс, чьим экземпляром он был создан, в данном случае MapObject. Поэтому его можно скастовать для сохранения в переменной с Типом MapObject и вызывать у него методы класса MapObject. В Вашем "аналоге" Вы пытаетесь вызывать у экземпляра класса В (а точнее – у null, ибо кастинг вернет null) методы класса С. Откуда же им взяться?
Еще раз. Кастинг не меняет класс объекта. Он проверяет, можно ли использовать объект как определенный Тип данных, и возвращает null, если нельзя (как в Вашем примере). Другими словами, если в массив из первого примера сложить экземпляры другого класса, они не будут кастоваться в MapObject, as вернет null и Вы получите ошибку.
Класс это то, чем объект "является" сам по себе. А тип это то, как он используется в текущем контексте. Это может быть реальный класс объекта, любой из его супер-классов и любой из его Интерфейсов. Но никак не любой класс, который взбредет в голову.

goldlider 14.11.2011 13:14

Цитата:

Сообщение от КорДум (Сообщение 1045933)
Потому что это приведение к типу. А не конвертирование в тип.

Какая разница между этими двумя понятиями? По мне это одно и тоже.

КорДум 14.11.2011 13:19

Wolsh выше все очень подробно расписал.

-De- 14.11.2011 13:41

Я лично тоже ничего б не понял из обьяснений Wolsh %) По-моему класс может вполне употребляться в смысле тип и наоборот. Обьект (какого-то класса или обьект какого-то типа) можно говорить в смысле переменная/экземпляр класса.

Про конвертацию лучше на примере.

Код AS3:

var Name:String = (new Sprite()).toString();//это конвертация в тип String, Sprite не имеет никакого отношения к Sprite, при конвертации создается новый экземпляр класса/типа String.
trace(Name);
//конвертация из типа в тип существует достаточно редко, в основном в строку =)
 
var ObjectSprite:Object= new Sprite();
var ObjectDO:DisplayObject = ObjectSprite as DisplayObject;//не null, новый обьект не создался, это наш спрайт, это приведение. Привести к базовому классу можно всегда
var ObjectSameSprite:Sprite = ObjectSprite as Sprite;//не нулл, приводим
var ObjectMC:MovieClip = ObjectSprite as MovieClip ;//null, Sprite не приводится к MovieClip
//попробуйте заменить new Sprite() на new MovieClip


goldlider 14.11.2011 14:31

-De-, это все понятно. В данных примерах Sprite яв-ся потомком класса DisplayObject. Вы объясните вот что, сама операция as меняет тип переменной или же нет. Т.е.
Код AS3:

msg:B
(msg as C)

поменяет ли тип переменная msg на тип C? Если да, то только в том случае если C яв-ся подтипом типа B?

Котяра 14.11.2011 14:47

Не меняет, а только приводит.
Конструкция
Цитата:

msg:B
(msg as C)
сработает только если B extends C или B implement С, но никак не наоборот

goldlider 14.11.2011 14:57

Цитата:

Сообщение от Котяра (Сообщение 1045963)
Не меняет, а только приводит.
Конструкция

сработает только если B extends C или B implement С, но никак не наоборот

То, что вы говорите это тоже самое что:
Код AS3:

var ObjectSprite:MovieClip = new Sprite();
ObjectSprite as MovieClip;

Такого быть не может. MovieClip extends Sprite, а не наоборот.

Что вы подразумеваете под словом приводит. Не понятно. Дайте какой-нибудь синоним данного слова. Если msg as C не меняет тип C, то это означает что переменная msg сохраняет тип B, и получается что строчка msg as C проводит проверку яв-ся тип переменной msg супертипом для C.

GBee 14.11.2011 15:18

Приводить можно к родителям или к их родителям и так далее.
Вы похожи на папу, а не папа похож на вас. Таким образом можно объявить переменную типа ПАПА, а создать ВАС. Но нельзя объявить вас и создать папу.

Sprite папа MovieClipa

goldlider 14.11.2011 15:36

Цитата:

Сообщение от GBee (Сообщение 1045970)
Приводить можно к родителям или к их родителям и так далее.
Вы похожи на папу, а не папа похож на вас. Таким образом можно объявить переменную типа ПАПА, а создать ВАС. Но нельзя объявить вас и создать папу.

Sprite папа MovieClipa

Я знаю, что Sprite яв-ся папой для MovieClip. Этот пример
Код AS3:

var ObjectSprite:MovieClip = new Sprite();
ObjectSprite as MovieClip;

я приводил из слов Котяры.

Котяра говорит, что должно быть так
Код AS3:

msg:B = new C(); // class B extends C
(msg as C).helloBoys

Папа в данном случае класс B, а ребенок класс C. Так как в таком случае может переменная типа B к ребенку C.
Следовательно ошибка возникает верно. Мы не можем вызывать метод описанный в ребенке, если этот ребенок не расширяет родительский класс B.
Я же говорю так
Код AS3:

msg:B = new C(); // class C extends B
(msg as C).helloBoys


GBee 14.11.2011 15:56

Цитата:

Таким образом можно объявить переменную типа ПАПА, а создать ВАС. Но нельзя объявить вас и создать папу.
Код AS3:

var ObjectSprite:Sprite = new MovieClip(); //ЗЯ

Код AS3:

var ObjectSprite:MovieClip = new Sprite(); //НЕЛЬЗЯ

Котяра перепутал малек в A B C ваших.

Цитата:

Конструкция
Цитата:
msg:B
(msg as C)
сработает только если B extends C или B implement С, но никак не наоборот
Код AS3:

msg:B = new C(); // class B extends C НЕЛЬЗЯ
msg:С = new B(); // class B extends C МОЖНО
 
msg:B = new C(); // class C extends B МОЖНО
msg:С = new B(); // class C extends B НЕЛЬЗЯ

Папа умеет говорить ТОЛЬКО "привет, девочки"
Вы умеете говорить "привет, мальчики" - (daddy as I).приветМальчики(), но только при условии что в переменная daddy указывает на объект класса I (который расширяет Daddy)

Wolsh 14.11.2011 15:57

Да, верно))
Только если в переменную msg действительно записана ссылка на объект класса С, иначе получите null.

GBee 14.11.2011 15:58

class Я extends Папа

Я расширяю Папу :о) Папа в ООП проще.

Wolsh 14.11.2011 16:06

Я бы просто посоветовал напрячься и изжить из своего сознания употребление терминов Parent/Child (папа/я, родитель/ребенок) при разговоре о наследовании. Поможет избежать разных неприятных ситуаций, ибо эти термины не имеют никакого отношения к наследованию (хотя иногда употребляют выражение "родительский класс" вместо суперкласс, но думаю никто никогда не слышал о "детском классе").

GBee 14.11.2011 16:12

По правде сказать я уже сам запутался.

Короче

Код AS3:

class Daddy
{daddyMethod();}
 
class Son extends Daddy
{sonMethod();}
 
//var s:Son = new Daddy(); Нельзя
var d:Daddy = new Son(); //Можно
 
//1
d.daddyMethod(); //Можно
(d as Son).sonMethod(); //Можно
 
//2
var d:Daddy = new Daddy(); //Можно
d.daddyMethod(); //Можно
//(d as Son).sonMethod(); //Нельзя null.sonMethod();

Добавлено через 2 минуты
Цитата:

Я бы просто посоветовал напрячься и изжить из своего сознания употребление терминов Parent/Child (папа/я, родитель/ребенок) при разговоре о наследовании. Поможет избежать разных неприятных ситуаций, ибо эти термины не имеют никакого отношения к наследованию (хотя иногда употребляют выражение "родительский класс" вместо суперкласс, но думаю никто никогда не слышал о "детском классе").
Это попытка в натуральном виде объяснить. Иначе придется в биологию лезть, парнокопытные -> лошадка

goldlider 14.11.2011 16:39

Всем большое спасибо за помощь. Реально помогли разобраться с простыми вещами.


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

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