AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 04.03.2008, 18:34   #1  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Вызов метода базового класса
Привет всем!
Необходимо вызвать super(), где целевым является метод через класс выше.
Допустим, есть такая иерархия:
X++:
class A
{
	void foo()
	{
		//....
	}
}

class B extends A
{
	void foo()
	{
		super();
	}
}

class C extends B
{
	void foo()
	{
		super(); // вызвать метод foo() у класса A, не вызывая foo() у класса B
	}
}
Самое простое решение это вместо super() написать, то что лежит в методе A (//...)
Но тут проблемы начнутся, если кто-то изменит базовый класс, то есть то что подразумевает супер не произойдет, пока мы опять не изменим метод 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();
	//...                
    }
};
Может быть есть какие-нибудь способы обойти класс B?
Старый 04.03.2008, 18:50   #2  
nano3 is offline
nano3
Участник
 
57 / 24 (1) +++
Регистрация: 21.03.2007
->
Может добавить в класс А метод foo1()
X++:
class A
{
    void foo()
    {
        //....
    }

    void foo1()
    {
        this.foo();
    } 
}
Старый 04.03.2008, 19:27   #3  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Цитата:
Может добавить в класс А метод foo1()
Нет. Класс С для того и заводился, чтобы не менять классы верхнего уровня.
Старый 04.03.2008, 19:27   #4  
miklenew is offline
miklenew
Участник
Аватар для miklenew
MCBMSS
1C
Лучший по профессии 2009
 
1,688 / 433 (18) +++++++
Регистрация: 10.07.2006
Адрес: г. Ликино-Дулёво
Цитата:
Сообщение от Eldar9x Посмотреть сообщение
Привет всем!
Необходимо вызвать super(), где целевым является метод через класс выше.
Если абстракции для создания классов подобраны правильно, то вероятность такой необходимости минимальна.
У меня покрайней мере не разу не возникала.
А можно поподробнее.
Чё за классы, и чё за методы.
Ну если не сложно конечно.
Интересно просто очень стало.
Старый 04.03.2008, 19:47   #5  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Классы создания строк отгрузочных накладных
(пишу на память)
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  
miklenew is offline
miklenew
Участник
Аватар для miklenew
MCBMSS
1C
Лучший по профессии 2009
 
1,688 / 433 (18) +++++++
Регистрация: 10.07.2006
Адрес: г. Ликино-Дулёво
Как бы я сделал всё что выше 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();
        }
    }
}
А в методе createLines класса ProdJournalCreateBOM
X++:
Protected void createLines()
{
;
    this.preCreateLines();
    super();
}
А в своём классе уже будете перекрывать preCreateLines и не будете трогать createLines
За это сообщение автора поблагодарили: Eldar9x (1).
Старый 04.03.2008, 20:30   #7  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Согласен. Вариант хороший, большое спасибо.
Скорее всего, так и сделаю.
И все же придется править классы выше - хотелось именно этого избежать. К тому же, было бы интресно найти решение данной задачи, вообще говоря думал, можно что-нибудь с super() сделать, так чтобы вызывать метод того класса, который мне был бы нужен.
Старый 04.03.2008, 21:46   #9  
HorrR is offline
HorrR
Участник
 
340 / 30 (2) +++
Регистрация: 18.02.2008
Адрес: Киев
Только хотел отписать про создание копировального конструктора на дедушке. Но это всё-равно изменение деда, хоть и безопасное.
__________________
Axapta has seduced me deadly!
Старый 05.03.2008, 11:02   #10  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Цитата:
как вызвать метод "деда" ?
и там нет решения. Была мысль - может как-нибудь с дикт. классами покрутить можно...
Старый 05.03.2008, 12:26   #11  
HorrR is offline
HorrR
Участник
 
340 / 30 (2) +++
Регистрация: 18.02.2008
Адрес: Киев
Тоже думал, но вариант отпал. Ибо не слишком рациональный. На самом деле, если юзать Дикт классы, то можно сделать так: узнать имя дедушки, найти в AOT его узел, потом узел нужного метода, получить его соурс, подставить туда значения из переменных собственного класса и выполнить на лету. Реально, но коряво) По-моему, создание копировального конструктора на дедушке - небольшая жертва, тем более, что хоть это изменение и системного класса, стандартному функционалу оно никак не повредит.
__________________
Axapta has seduced me deadly!

Последний раз редактировалось HorrR; 05.03.2008 в 12:31.
За это сообщение автора поблагодарили: Eldar9x (1).
Старый 05.03.2008, 14:08   #12  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Цитата:
По-моему, создание копировального конструктора на дедушке - небольшая жертва, тем более, что хоть это изменение и системного класса, стандартному функционалу оно никак не повредит.
Действительно, работает. Его и использую, большое спасибо.
Старый 06.03.2008, 18:10   #13  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Кажется, рано обрадовался. Метод базового класса таким образом хоть и вызываются, зато теряются объекты объявленные на верхнем уровне.
Скажем, есть у нас объект некого класса, объявленный в ClassDeclaration деда. Этот объект в процессе работы инициализируется в наследнике нижнего уровня. Затем нам требуется вызвать метод деда, в котором с этим объектом что-то делаем (например, вызываем какой-нибудь его метод). Так, если проделать операции внутри наследника:
X++:
   void C::foo()
   {
    A pBaseOfThis; 
    ; 
    // здесь что-то делаем, чтобы инициализировать _объект_, объявленный в деде

   pBaseOfThis = new A(this); 
   pBaseOfThis.foo();  // здесь вызывается текущий метод деда, в котором идет обращение к      _объекту_
  }
то в результате окажется, что _объект_ не инициализирован. Вот такие вот дела....
Старый 06.03.2008, 18:43   #14  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
мне кажется, маленькая модификация метода будет более понятной, чем большой изврат
Старый 11.03.2008, 11:16   #15  
HorrR is offline
HorrR
Участник
 
340 / 30 (2) +++
Регистрация: 18.02.2008
Адрес: Киев
Попробуйте в копировальном конструкторе дедушки явно скопировать все его переменные с обьекта который вы копируете.

Ну что-то наподобии:
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  
ZVV is offline
ZVV
MCITP
MCP
Oracle
MCBMSS
 
1,006 / 246 (11) ++++++
Регистрация: 13.02.2004
Адрес: Минск
->
Цитата:
Сообщение от belugin Посмотреть сообщение
мне кажется, маленькая модификация метода будет более понятной, чем большой изврат
Поддерживаю.

Ещё как вариант можно добавить параметр _skip в метод, и в B обрабатывать его так, чтоб сразу вызывался super...
__________________
Zhirenkov Vitaly
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
вызов метода из таблицы в операторе while select V777 DAX: Программирование 7 23.04.2008 09:11
Вызов класса из другого класса Protey DAX: Программирование 9 26.02.2007 11:01
Вызов метода класса из HTML Chezer DAX: Программирование 2 26.12.2006 15:34
"Программный" вызов метода класса!? axaLearner DAX: Программирование 13 16.08.2005 08:12
вызов класса с передачей параметров simply DAX: Программирование 2 23.06.2004 18:04

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 18:23.