Форум Flasher.ru

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

orcpochta 04.03.2010 15:55

Недопонимание перекрытия методов суперкласса
 
Есть СуперКласс и НаследникКласс.
СуперКласс определяет метод testMethod( ), а НаследникКласс его переопределяет.

Могу ли я как-то вызвать над экземпляром класса НаследникКласс непереопределенный метод testMethod( ) класса СуперКласс?

т.е. экземплярНаследникКласс.testMethod( ) - вызывается переопределенный метод
а экземплярНаследникКласс.что-то-как-то.testMethod( ) - вызывает непереопределенный метод.

Мне казалось, что должно сработать через приведение:
СуперКласс(экземплярНаследникКласс).testMethod( )

Но это не работает, а так хотелось)))

GentleFLASH 04.03.2010 15:57

в НаследникКласс нужно вызвать super.testMethod() - это и будет непереопределенный метод СуперКласс'а

orcpochta 04.03.2010 16:05

Цитата:

Сообщение от GentleFLASH (Сообщение 890934)
в НаследникКласс нужно вызвать super.testMethod() - это и будет непереопределенный метод СуперКласс'а

не-не-не... мне нужно не в классе его вызывать, а снаружи над экземпляром, т.е. иметь возможность вызывать обе версии метода над экземпляром

iNils 04.03.2010 16:24

Цитата:

мне нужно
Не нужно. Метод для того и переопределяется.
Хотите иметь два разных, сделайте в наследнике другой метод где и будет переопределенный код.

GentleFLASH 04.03.2010 17:05

ну если через namespace, а может и не получится..

orcpochta 04.03.2010 17:15

Цитата:

Сообщение от iNils (Сообщение 890947)
Не нужно. Метод для того и переопределяется.
Хотите иметь два разных, сделайте в наследнике другой метод где и будет переопределенный код.

Вдумайтесь как все могло бы быть красиво))))

Для примера возьмем toString( ). Есть стандартный toString( ) для Object. Для нашего класса определим свой toString( ), для подкласса тоже свой и т.д. Получаем, что для одного экземпляра можно было бы вызывать любой toString( ) через приведение:
trace(instance);
trace(SuperClass(instance));
trace(Object(instance));

Живой пример:
Есть класс, представляющий структуру данных, например, таблицу - Table. Метод toString( ) делает строку из элементов этой таблицы. Есть расширяющий класс субтаблица (фрагмент таблицы) SubTable - по сути та же таблица, хранящая вместо элементов или значений ссылки (индексы) на ячейки основной таблицы, т.е., работая с субтаблицей, мы по сути работаем с исходной таблицей, но только в окрестностях, ограниченных нашей субтаблицей.
В классе SubTable, если не переопределять toString( ), будет получаться строка ссылочных индексов на исходную таблицу, но логично будет его переопределить так, чтобы выдавалась строка конечных значений таблицы в окрестности субтаблицы.
Тогда мы могли бы выводить значения ячеек субтаблицы через
trace(subtable);
а саму фактическую таблицу (т.е. таблицу индексов, ссылающихся на исходную таблицу, через которые описывается связь субтаблицы и примарной таблицы) через
trace(Table(subtable));

Красиво же)))

GentleFLASH 04.03.2010 17:32

Это на виртуальные методы по описанию похоже. В AS3 хоть и есть ключевое слово virtual, только вот оно не работает. В википедии про виртуальные функции написано и в инете есть примеры на AS3, где они не работают.

chabapok 04.03.2010 17:54

Хм, а если явно указать класс, которым итерпретировать объект. Не гарантирую что выйдет, но попробуйте так:
(obj as SupserClass).superClassMethod();
(obj as SuperUnderSuperClass).superClassMethod();
и тд.

ps_spectre 04.03.2010 17:55

[offtop]
Виртуальные функции работают как надо в АС3. Так что не надо. :D см след. страницу. )
Код AS3:

 
class Foo extends Object
{
        public virtual function Test():void
        {
                trace("Foo.Test()");
        }
}
class Bar extends Foo
{
        public override function Test():void
        {
                trace("Bar.Test()");
        }
}
class Biz extends Bar
{
        public override function Test():void
        {
                trace("Biz.Test()");
        }
}
====
 
                        var f:Foo = new Foo();
                        f.Test();
                        f = new Bar();
                        f.Test();
                        f = new Biz();
                        f.Test();

[/offtop]

relevance4 04.03.2010 18:49

Цитата:

Сообщение от orcpochta (Сообщение 890966)
Красиво же)))

красиво будет сделать метод, в который передаются индексы субтаблиц (или как там у вас устроено), которые нужно получить в виде строки и ещё один метод для получения строки всех таблиц, который, кстати, будет дёргать метод с индексами.

мне по крайней мере видится так (:

orcpochta 04.03.2010 19:51

Цитата:

Сообщение от chabapok (Сообщение 890988)
Хм, а если явно указать класс, которым итерпретировать объект. Не гарантирую что выйдет, но попробуйте так:
(obj as SupserClass).superClassMethod();
(obj as SuperUnderSuperClass).superClassMethod();
и тд.

нет, так тоже не работает

etc 04.03.2010 19:52

Цитата:

Сообщение от ps_spectre (Сообщение 890989)
Виртуальные функции работают как надо в АС3. Так что не надо.

Не работают, нет эксепшена о том, что метод не переопределен.

orcpochta 04.03.2010 19:54

Цитата:

Сообщение от ps_spectre (Сообщение 890989)
[offtop]
Виртуальные функции работают как надо в АС3. Так что не надо.
[/offtop]

не понял, что вы хотели этим сказать

компилируется - это еще не значит работает
убрать модификатор virtual и разве что-то изменится?

wvxvw 04.03.2010 20:02

На уровне байткода можно создать виртуальную функцию - только оно вам надо? :)

ps_spectre 04.03.2010 20:05

Убедили, назвать нормальной работой - сложно,)

chabapok 04.03.2010 22:30

тогда можно попробовать как-то так
делаем интерфейс

Код AS3:

interface IClassWhoCanCallGrandSuper{
 function callGrandSuper(funcName:String, level);
}
//и наследуем его в базовом классе определив функцию
 
function callGrandSuper(funcName:String, level){
 if (level==0) return this[funcName]();
 else return super.callGrandSuper(funcName, level-1);
}
 
вызываем
 
obj.callGrandSuper(myfunc, 3); //myfunc прадедушки

ну, это только идея, я не проверял как оно работать будет. И даже если будет работать - решение не очень. Не факт, что вызов функции в прадедушки сработает в прадедушку - очень может быть, что этого не произойдет, и тогда просто прийдется прицеплять такой кусок к той функции, которую вы хотите вызывать:

Код AS3:

function myfunc(level=0){
 if (level>0) return super.lmyfunc(level-1)//это цепляем на каждом уровне вложенности
 
 блаблабла ;//это код самой функции на данном уровне вложенности
}
 
//и вызываем:
obj.myfunc(1);//родитель
obj.myfunc(2);//дед
obj.myfunc(3);//прадед и тд
//этот вариант будет работать точно.
//может так даже удобней - не надо писать конструкции типа
//obj.super.super.super.super.myfunc()

и можно еще попытаться (UPD: попытался - не работает, может кто скажет почему?) с именем класса поиграться как-то так (тут тоже не знаю сработает ли проверка (super is NeedClass) ):
Код AS3:

function myfunc(NeedClass){
 if (super is NeedClass) renturn super.myfunc(NeedClass);
 блаблабла;//код на текущем уровне вложенности
}

Добавлено через 23 минуты
последний вариант рабочий если в сравнении написать так:
if (prototype != NeedClass.prototype) return super.myfunc(NeedClass);

orcpochta 07.03.2010 03:49

А вот кстати какая подстава:
Если в суперклассе есть два метода (не private), один из которых вызывается другим:
Код AS3:

public function A ( ):void
{
    B( );
}
 
public function B ( ):void
{
    trace("SuperClass, function B");
}

и класс-наследник перекрывает этот метод суперкласса (вызывающийся из другого метода суперкласса)

Код AS3:

override public function B ( ):void
{
    trace("Extension, function B")
}

то связка методов "A суперкласса вызывает B суперкласса" становится недоступна из класса наследника, а получаем "А суперкласса вызывает B класса-наследника" (что рушит логическую цепочку ф-ий и приводит к непредсказуемым последствиям)

или есть какой-то способ указать, что А должен вызвать B суперкласса, а не B класса-наследника? может как-то через пространства имен?

P.S. сейчас придет многоуважаемый iNils и скажет, что надо называть методы разными именами, а override - он на то и override)))

etc 07.03.2010 22:47

orcpochta, предлагаю финализировать B в A.


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

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