Просмотр полной версии : Как вызвать непереопределенный метод в базовом классе
В соседней ветке речь зашла про super, и там меня похоже не совсем правильно поняли.
Поэтому, чтобы не усложнять пример 2мя классами, рассмотрю вариант только с одним, базовым.
Есть класс, есть в нем объявленный метод methodA, который может быть переопределен наследником. Как мне в базовом классе вызвать без обходных путей непереопределенный метод methodA? Вызываю super.methodA(), а в трэйс вываливается ран-тайм ошибка. Может я в чем то ошибся? Или это так и задумано?
код вызова:
var _a:ClassA = new ClassA();
trace( "_a.methodA(): " + _a.methodA() );
trace( "_a.methodA_super(): " + _a.methodA_super() );
ClassA:
package
{
public class ClassA
{
public function ClassA()
{
}
public function methodA():String
{
return "ClassA::methodA()";
}
public function methodA_super():String
{
return super.methodA();
}
}
}
трэйс:
_a.methodA(): ClassA::methodA()
ReferenceError: Error #1070: Method methodA not found on Object
at ClassA/methodA_super()
at test_fla::MainTimeline/frame1()
incvizitor
07.05.2010, 18:42
Сейчас попробовать не могу, но может вот так:
package
{
public class ClassA
{
private var _thisA:Function;
public function ClassA()
{
_thisA=this.methodA;
}
public function methodA():String
{
return "ClassA::methodA()";
}
public function methodA_super():String
{
return _thisA();
}
}
}
?
Думаю надо в этом направлении думать.
Спасибо. Просто думаю это как раз один из обходных путей. Хочется узнать почему простого super.methodA() недостаточно
Так то и так можно организовать, и тоже все гуд будет:
package
{
public class ClassA
{
public function ClassA()
{
}
public function methodA():String
{
return _super_methodA();
}
private function _super_methodA():String
{
return "ClassA::methodA()";
}
public function methodA_super():String
{
// return super.methodA();
return _super_methodA();
}
}
}
Но какое то чувство остается, что должно быть проще ))
Вызываю super.methodA(), а в трэйс вываливается ран-тайм ошибка.
Ну правильно, я так понимаю раз класс ничего не расширяет, то по-дефолту он расширяет Object.
Вот он тебе и пишет в эксепшене что у Object нет такого метода.
Вообщем помоему постановка задачи какая то кривая очень, раз нет никакого наследования здесь - к чему тогда вообще super и всё подобное.
incvizitor
07.05.2010, 19:10
Можно так, но это как то не красиво :(
final public function methodA_super():String
{
if(getQualifiedClassName(this)!="ClassA"){
if(getQualifiedClassName(super)=="classA")
return super["methodA"];
else
return super["methodA_super"];
}
else
return methodA();
}
Что тут происходит, расскажите мне))
Ну или расскажите, что принять нужно, чтобы это понять?)
Есть класс, есть в нем объявленный метод methodA, который может быть переопределен наследником. Как мне в базовом классе вызвать без обходных путей непереопределенный метод methodA?
this.methodA();
раз нет никакого наследования здесь - к чему тогда вообще super и всё подобное.
Да потому что с наследованием тоже самое. Написал же в самом начале, что упростил до одного класса специально.
Вот с наследованием. Как мне вызвать непереопределленный метод суперкласса из самого же суперкласса?
код:
var _b:ClassB = new ClassB();
trace( "_b.methodA(): " + _b.methodA() );
trace( "_b.methodA_simple(): " + _b.methodA_simple() );
trace( "_b.methodA_super(): " + _b.methodA_super() );
ClassA:
package
{
public class ClassA
{
public function ClassA()
{
}
public function methodA():String
{
return "ClassA::methodA()";
}
final public function methodA_simple():String
{
return this.methodA();
}
final public function methodA_super():String
{
return super.methodA();
}
}
}
ClassB:
package
{
public class ClassB extends ClassA
{
public function ClassB()
{
super();
}
override public function methodA():String
{
return "ClassB::methodA()";
}
}
}
трэйс:
_b.methodA(): ClassB::methodA()
_b.methodA_simple(): ClassB::methodA()
ReferenceError: Error #1070: Method methodA not found on Object
at ClassA/methodA_super()
at test_fla::MainTimeline/frame1()
Вот как мне сделать, чтобы methodA_super() всегда вызвал непереопределенный methodA(), т.е чтобы возвращал "ClassA::methodA()". Я вот хочу в суперклассе ClassA всегда работать с непереопределенным методом methodA(). Как мне это сделать без всяких private function _super_methodA():String
Почему при вызове super.methodA(); лезет в Object, если суперкласс метода - это ClassA?
incvizitor
07.05.2010, 19:27
cauchy, если у Вас есть объект класса ClassA то при вызове methodA_super (такое же тоже возможно) он вернет methodA. В обратном случае класс будет вызывать свойство methodA_super своего суперкласса, таким образом рекурсивно добираясь до класса который непосредственно расширяет ClassA. Но метод предложенный i.o. намного лучше.
incvizitor, похоже вы перепутали getDefinitionByName() с getQualifiedClassName().
В общем подставил, ничего не изменилось.
Помнится wvxvw любит использовать super. Он наверняка знает ответ )
incvizitor
07.05.2010, 19:44
Да, перепутал :) Ну не знаю, я написал:
super.methodA();
выдало ошибку при компиляции.
super["methodA"]
Ошибку при компиляции не выдало.
Flash CS4 и FlashDevelop не выдают ошибку компиляции, только рантайм
incvizitor
07.05.2010, 20:12
Ну я пишу в FlashDevelop, но компилю в CS3
Спасибо за разъяснения, суть задачи понял (просто какое-то необычное чуть-чуть применение, поэтому долго не мог сообразить).
Чем помочь пока не знаю.
ps: если classA ничего не расширяет то компиляция проходит, если расширяет, например, Sprite то уже не компилится (ну впринципе логично, не может найти такой метод в спрайте).
incvizitor
07.05.2010, 23:22
Можно попробовать:
var prop:String="methodA";
super[prop];
Хотя у мяне компилилось и так даже если Sprite расширяло.
Добавлено через 50 секунд
Flash CS4 и FlashDevelop не выдают ошибку компиляции, только рантайм
Так подожди, это разве не значит что проблема решена?
В общем, понял что никак через super не получится. super всего лишь ссылка на базовый класс. Т.е если в базовом классе понадобится вызов непереопределенной функции, то реализовать лучше всего так (через приватную функцию):
package
{
public class ClassA
{
public function ClassA()
{
}
public function methodA():String
{
return _super_methodA();
}
private function _super_methodA():String
{
return "ClassA::methodA()";
}
public function methodA_super():String
{
return _super_methodA();
}
}
}
Всем, кто принимал учвстие в обсуждении - спасибо)
Есть класс, есть в нем объявленный метод methodA, который может быть переопределен наследником. Как мне в базовом классе вызвать без обходных путей непереопределенный метод methodA?
package {
public class ClassA {
public function methodA():String {
return this.$methodA();
}
public function methodA_super():String {
return this.$methodA();
}
/**
* @private
* реализация метода
*/
private function $methodA():String {
return "ClassA::methodA()";
}
}
}
BlooDHounD
09.05.2010, 04:41
dimarik, я всё ждал когда же они сами к этому придут, а ты всё испортил.
dimarik, большое спасибо. Этот было еще в постах номер 3 и 15. Знак $ сути не меняет )
Димка, постом выше было тоже самое :D
Zebestov
10.05.2010, 16:17
ахинея все... особенно после единственно правильного ответа в посте #6...
хотя может все просто из-за того что я не курю запрещенных трав...
не хочу поднимать ахинею снова, но this.methodA() из шестого поста как раз может быть вызван переопределенным, поэтому правильный ответ в постах 3, 15 ну и, естесственно, 16
Zebestov
11.05.2010, 00:16
0о т.е. в базовом классе A вызов this.methodA() вызовет не A::methodA()? куда катится мир...
P.S.
может я просто не уловил сути.
тут часом не обсуждается навязчивая идея использовать super в базовом классе, расширяющим Object (т.е. ничего), и чтобы все работало?
если так — то я мимо... и это просто забава такая для тренировки ума... как эспандер =) никакой полезной работы для Отечества.
Часом не обсуждается. Я думал что непереопределенный метод можно было вызвать по-простому - super.methodA(). Однако этот метод ищется действительно в супере, т.е в Object. Вариант только однин (без закидонов) - написать приватный метод, реализующий "родной" methodA. А на счет this.methodA() - если в классе СassB я его переопределю, то в СlassA, который нуждается в "родном" methodA(), вызовется уже переопределенный. Т.е будет B::methodA().
Если совсем непонятно про что речь и к чему это все. То в двух словах:
Есть базовый класс, в котором есть public function _2x2():int, и она всегда для базового класса должна отдавть естественно 4.
Но вот в один день мне вдруг взгрустнулось, и я решил расширить сласс, да так, чтобы для нужд нового расширенного класса, эта самая функция могла бы возвращать, скажем -4.
Если базовый класс будет вызывать this._2x2(), то, естественно, он будет давать результаты, мягко скажем не те, какие ожидаются. Так вот чтобы его логика не нарушалась, и нужно в базовом классе как то вызывать "родную" _2x2(). А как это сделать уже выяснили.
Zebestov
11.05.2010, 01:39
приехали... наследуемый класс переопределяя метод оказывается переопределяет его и в суперклассе... пошел смотреть сериал...
0о т.е. в базовом классе A вызов this.methodA() вызовет не A::methodA()? куда катится мир...this указывает не на класс, а на экземпляр. А экземпляр в данном случае - экземпляр класса-наследника. И методы у этого экземпляра - класса-наследника. Всё более чем логично.
Zebestov, вот если не веришь или лень проверять...
Представляю вашему обозрению пост номер 7. Особое внимание прошу уделить трэйсу:
_b.methodA_simple(): ClassB::methodA()
Еще вопросы или недоверия есть?
Zebestov
11.05.2010, 03:28
я очень прошу. можно еще раз, другими словами, популярно пояснить — чего мы хотим? Пост #7 с демонстрацией того, как все запущено, мне в упор не понятен.
ну надо тебе иметь базовый класс, ну опиши его:
public class ClassA
{
public function ClassA():void
{
}
public function methodA():String
{
return "ClassA::methodA()";
}
}
надо тебе его расширить, ну расширяй:
public class ClassB extends ClassA
{
public function ClassB()
{
super();
}
override public function methodA():String
{
return "ClassB::methodA()";
}
}
и ты утверждаешь, что теперь будет так:
var _a:ClassA = new ClassA();
var _b:ClassB = new ClassB();
trace(_a.methodA()); // думаешь, что выведет "ClassB::methodA()",
// потому что мы его переопределили в наследнике
или о чем вообще три страницы?
о том что:
var _b:ClassB = new ClassB();
trace(_b.methodA()); // таки выведет "ClassB::methodA()",
// потому что мы его переопределили в наследнике
а ты хотел, чтобы вывело "ClassA::methodA()"? тогда зачем ты вообще его переопределял?
или ты хочешь одной иметь в экземпляре класса B возможность вызвать и переопределенный и непереопределенный методы? тогда зачем ты вообще грузишь этими проблемами суперкласс A? Допиши в ClassB новый метод, скажем, methodAsuper(), в котором вызываешь просто super.methodA(). и будет твое заветное:
var _b:ClassB = new ClassB();
trace(_b.methodAsuper()); // таки выведет "ClassA::methodA()",
но не в ClassA же это делать. не его головная боль, что ты там навыдумывал в наследнике.
Zebestov, не утруждайте себя, вопрос был в другом. Если бы вы хотели понять, о чем идет тут речь, то задумались бы, почему тема началась всего лишь с одного класса. Я не собираюсь тут каждому на пальцах разъяснять, что хотел. Тем более что ответ давным давно получен.
Индивидуально для Zebestov попробую в последний раз объяснить все же:
У меня есть базовый класс А, так вот в нем все должно работать всегда одинаково и исправно, несмотря на то, что некоторые его методы, можно переопределить. Т.е он должен уметь вызывать свои родные методы. Наследники тут не при чем, это просто для примера было. Из наследников нет необходимости вызывать супер методы. В трэйсе для примера были вызовы, чтобы показать, что именно вызывается в базовом классе. Все ли сейчас понятно?
Сама задача проще некуда, просто решил узнать есть ли способ обойтись без создания дополнительных приватных функций, вот и все. Хотелось вызывать непереопределенный метод так же, как и в наследниках - super.methodA(), но так не получается.
Zebestov
11.05.2010, 14:00
Индивидуально для Zebestov попробую в последний раз объяснить все же:
У меня есть базовый класс А, так вот в нем все должно работать всегда одинаково и исправно, несмотря на то, что некоторые его методы, можно переопределить.
благодарю за индивидуальный подход =)
что-то подозреваю, но еще хочу уточнить. под "некоторые его методы можно переопределить" ты имеешь в виду непосредственно через месячишко взять этот же класс и переписать его метод(ы) с какими-то сколь-нибудь существенными изменениями? и чтобы при этом по прежнему можно было пользовать еще и старые версии?
что-то подозреваю, но еще хочу уточнить. под "некоторые его методы можно переопределить" ты имеешь в виду непосредственно через месячишко взять этот же класс и переписать его метод(ы) с какими-то сколь-нибудь существенными изменениями? и чтобы при этом по прежнему можно было пользовать еще и старые версии?
Нет. Если прикалываешься, то это уже не весело ))
Zebestov
11.05.2010, 14:22
не прикалываюсь. просто термин "переопределение" (в контексте темы) уместно применять лишь при наследовании. новый класс наследует базовый и переопределяет его метод(ы). а переписывать метод в процессе программирования по несколько раз — это ну там отладка или еще что.
я искренен с тобой =) я не могу разобрать, что ты понимаешь под переопределением, при этом говоря, что речь не идет о наследниках. 0о
переопределение = override
что еще непонятно?
Zebestov
11.05.2010, 14:30
override — в новом классе B, который ты унаследовал от базового A, в котором, в свою очередь, этот метод уже существует и к нему из B всегда можно обратиться через super. все верно? т.е. если его не существует, то и override не сделаешь и через super не обратишься. так?
Zebestov
11.05.2010, 14:42
так оно так и работает =) в чем подвох? в чем "задача" =) сохранить где-то оригинал метода?
ну так для этого не Object нужен, а класс A, который не для широкого использования, а для наследования под конкретный случай. и уже в коде используются его детки B, C, D, etc., в которых что-то добавлено, что переопределено. и класс A всегда неизменен, и все детки super-а могут позвать в любой момент.
Ну все так ведь?
Все так. Задача в том чтобы класс А только со своим первоначальным методом работал, вот и все
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.