04.03.2008, 18:34 | #1 |
MCTS
|
Вызов метода базового класса
Привет всем!
Необходимо вызвать super(), где целевым является метод через класс выше. Допустим, есть такая иерархия: X++: class A { void foo() { //.... } } class B extends A { void foo() { super(); } } class C extends B { void foo() { super(); // вызвать метод foo() у класса A, не вызывая foo() у класса B } } Но тут проблемы начнутся, если кто-то изменит базовый класс, то есть то что подразумевает супер не произойдет, пока мы опять не изменим метод foo() класса C Другой вариант: X++: class C extends B { void foo() { A a; ; a = this; a.foo(); } } X++: A a; ; a = this; a.foo(); И к тому же, вполне вероятно, что это не сработает. Если считать foo виртуальной функцией, то получаем - вызов a.foo() вызовет C::foo() и как результат - бесконечная рекурсия с переполнением стека. То есть требуется, что то вроде: X++: class C : public B { public: virtual void foo() { A::foo(); //... } }; |
|
04.03.2008, 18:50 | #2 |
Участник
|
Может добавить в класс А метод foo1()
X++: class A { void foo() { //.... } void foo1() { this.foo(); } } |
|
04.03.2008, 19:27 | #3 |
MCTS
|
Цитата:
Может добавить в класс А метод foo1()
|
|
04.03.2008, 19:27 | #4 |
Участник
|
Цитата:
У меня покрайней мере не разу не возникала. А можно поподробнее. Чё за классы, и чё за методы. Ну если не сложно конечно. Интересно просто очень стало. |
|
04.03.2008, 19:47 | #5 |
MCTS
|
Классы создания строк отгрузочных накладных
(пишу на память) ProdJournalCreate ProdJournalCreateBOM ProdJournalCreateLocation - мой класс Там есть метод createLines. В стандарте - создает строки по одному JournalNameId (это есть B). Мой класс (С) создает отдельные журналы для каждого склада BOM, используя при этом дополнительную функциональность класса В. Для этого есть таблица соответствий JournalNameId->Склад. В классе ProdJournalCreate (A) в методе CreateLines только завершающая операция. Вот и нужно, создать строки следуя алгоритму разбивки по складам, а затем вызвать super() класса A, не вызывая при этом алгоритм "по одному JournalNameId". А в ProdJournalCreate - только две строки - собственно запись в бд (ProdJournalCreate->CreateLines). Последний раз редактировалось Eldar9x; 04.03.2008 в 19:55. |
|
04.03.2008, 20:13 | #6 |
Участник
|
Как бы я сделал всё что выше super() в классе ProdJournalCreateBOM вынес бы в отдельный метод
X++: Protected void preCreateLines() { ProdJournalBOM prodJournalBOM; ProdBOMCalc prodBOMCalc; ProdBOM prodBOM; BOMCalcData BOMCalcData = BOMCalcData::newProdTable(qtyCalc,ProdTable::find(prodId)); ; setPrefix("@SYS28536"); this.initProdJournalTableData(prodJournalType::Picklist); prodJournalTransData = prodJournalTableData.JournalStatic().newJournalTransData(prodJournalBOM,prodJournalTableData); if (prodJournalTable.NumOfLines) prodJournalTransData.parmLastLineNum(prodJournalBOM::lastLineNum(journalId)); if (! oprNumTo) oprNumTo = oprNumFrom; BOMCalcData = BOMCalcData::newProdTable(qtyCalc,ProdTable::find(prodId)); while select forupdate prodBOM index hint numIdx where prodBOM.prodId == prodId && prodBOM.OprNum >= oprNumFrom && (prodBOM.OprNum <= oprNumTo || ! oprNumTo) { prodBOMCalc = prodBOMCalc::newBOMCalcData(BOMCalcData,prodBOM,ConsumpProposal,BOMAutoConsump,! prodBOM.ConstantReleased, shipAccError); if (prodBOMCalc.hasQty() || (endUpdate && prodBOM.backorderStatus == ProdBackStatus::Release)) { prodJournalTableData.initJournalId(); this.initTransFromProdBOM(prodJournalBOM,prodBOM); ProdBOMCalc.setProdJournalBOM(prodJournalBOM); if (ConsumpAsProposal) { prodJournalBOM.BOMConsump = prodJournalBOM.BOMProposal; prodJournalBOM.inventConsump = prodJournalBOM.inventProposal; } if (proposalAsConsump) { prodJournalBOM.BOMProposal = prodJournalBOM.BOMConsump; prodJournalBOM.inventProposal = prodJournalBOM.inventConsump; } prodBOM.ConstantReleased = noYes::Yes; prodJournalBOM.insertJournalCreate(prodJournalTransData,prodBOM); if (prodBOM.ConstantReleased != prodBOM.orig().ConstantReleased) prodBOM.doUpdate(); } } } X++: Protected void createLines() { ; this.preCreateLines(); super(); } |
|
|
За это сообщение автора поблагодарили: Eldar9x (1). |
04.03.2008, 20:30 | #7 |
MCTS
|
Согласен. Вариант хороший, большое спасибо.
Скорее всего, так и сделаю. И все же придется править классы выше - хотелось именно этого избежать. К тому же, было бы интресно найти решение данной задачи, вообще говоря думал, можно что-нибудь с super() сделать, так чтобы вызывать метод того класса, который мне был бы нужен. |
|
04.03.2008, 21:46 | #9 |
Участник
|
Только хотел отписать про создание копировального конструктора на дедушке. Но это всё-равно изменение деда, хоть и безопасное.
__________________
Axapta has seduced me deadly! |
|
05.03.2008, 11:02 | #10 |
MCTS
|
Цитата:
как вызвать метод "деда" ?
|
|
05.03.2008, 12:26 | #11 |
Участник
|
Тоже думал, но вариант отпал. Ибо не слишком рациональный. На самом деле, если юзать Дикт классы, то можно сделать так: узнать имя дедушки, найти в AOT его узел, потом узел нужного метода, получить его соурс, подставить туда значения из переменных собственного класса и выполнить на лету. Реально, но коряво) По-моему, создание копировального конструктора на дедушке - небольшая жертва, тем более, что хоть это изменение и системного класса, стандартному функционалу оно никак не повредит.
__________________
Axapta has seduced me deadly! Последний раз редактировалось HorrR; 05.03.2008 в 12:31. |
|
|
За это сообщение автора поблагодарили: Eldar9x (1). |
05.03.2008, 14:08 | #12 |
MCTS
|
Цитата:
По-моему, создание копировального конструктора на дедушке - небольшая жертва, тем более, что хоть это изменение и системного класса, стандартному функционалу оно никак не повредит.
|
|
06.03.2008, 18:10 | #13 |
MCTS
|
Кажется, рано обрадовался. Метод базового класса таким образом хоть и вызываются, зато теряются объекты объявленные на верхнем уровне.
Скажем, есть у нас объект некого класса, объявленный в ClassDeclaration деда. Этот объект в процессе работы инициализируется в наследнике нижнего уровня. Затем нам требуется вызвать метод деда, в котором с этим объектом что-то делаем (например, вызываем какой-нибудь его метод). Так, если проделать операции внутри наследника: X++: void C::foo() { A pBaseOfThis; ; // здесь что-то делаем, чтобы инициализировать _объект_, объявленный в деде pBaseOfThis = new A(this); pBaseOfThis.foo(); // здесь вызывается текущий метод деда, в котором идет обращение к _объекту_ } |
|
06.03.2008, 18:43 | #14 |
Участник
|
мне кажется, маленькая модификация метода будет более понятной, чем большой изврат
|
|
11.03.2008, 11:16 | #15 |
Участник
|
Попробуйте в копировальном конструкторе дедушки явно скопировать все его переменные с обьекта который вы копируете.
Ну что-то наподобии: X++: Ded_value_X=Object2Copy.Get_Ded_value_X() UPD С другой стороны в таком случае удобно сделать на дедушке конструктор, который в параметрах принимал бы контейнер, содержащий переменные внука и из этого контейнера инитил бы свои.
__________________
Axapta has seduced me deadly! Последний раз редактировалось HorrR; 11.03.2008 в 13:54. |
|
22.03.2008, 19:10 | #16 |
MCITP
|
Цитата:
Ещё как вариант можно добавить параметр _skip в метод, и в B обрабатывать его так, чтоб сразу вызывался super...
__________________
Zhirenkov Vitaly |
|