07.11.2018, 15:54 | #1 |
Участник
|
D365FO: Inheritance + Extensions + RealTime
Есть 8.0 PU15. Переношу overlaid-решение на extensions.
В классе InventMovement был кастом-метод, который был перекрыт в наследниках (InventMov_Purch) Я создал extensions к этим методам и ожидаю, что в real-time вызовется нужный extension: X++: [ExtensionOf(classStr(InventMovement))] final class InventMovementAQM_Extension { boolean AQMmustUpdateBatchInfo() { return false; } } [ExtensionOf(classStr(InventMov_Purch))] final class InventMov_PurchAQM_Extension { boolean AQMmustUpdateBatchInfo() { return true; } } X++: [ExtensionOf(tableStr(InventBatch))] final class InventBatchAQM_Extension { public void initFromInventMovement(InventMovement _inventMovement, InventTrans _inventTrans) { next initFromInventMovement(_inventMovement, _inventTrans); if (_inventMovement.AQMmustUpdateBatchInfo()) { // blablabla } } Если сделать явное преобразование X++: InventMov_Purch invMov;
invMov = _inventMovement;
if (invMov.AQMmustUpdateBatchInfo())
{
} Как Вы считаете - это баг? В 8.1\8.1.1\8.1.2 система ведет себя также? |
|
07.11.2018, 17:11 | #2 |
Участник
|
Wrapping a base method in an extension of a derived class
The following example shows how to wrap a base method in an extension of a derived class. For this example, the following class hierarchy is used. X++: class A { public void salute(str message) { info(message); } } class B extends A {} class C extends A {} X++: [ExtensionOf(classStr(B))] final class B_Extension { public void salute(str message) { next salute(message); info("B extension"); } } This behavior becomes clearer if we implement a method that uses these three classes. X++: class ProgramTest { public static void main(Args args) { var a = new A(); var b = new B(); var c = new C(); a.salute("Hi"); b.salute("Hi"); c.salute("Hi"); } } By using this mechanism, you can wrap the original method only for specific derived classes. https://docs.microsoft.com/en-us/dyn...d-wrapping-coc
__________________
Felix nihil admirari Последний раз редактировалось wojzeh; 07.11.2018 в 17:13. |
|
07.11.2018, 18:30 | #3 |
Участник
|
Цитата:
(Thank you for your answer. I have the different case: I havn't COC. I have extensions for parent class and for a child. Both extensions has the same method. A class variable declared as a parent class, but initialized as a child. The system invokes extension for the parent class) X++: class A { } class B extends A { } [ExtensionOf(classStr(A))] final class A_Extension { public void salute() { info("A extension"); } } [ExtensionOf(classStr(B))] final class B_Extension { public void salute() { info("B extension"); } } X++: class Test01 { public static void main(Args _args) { A a; a = new B(); a.salute(); } } |
|
|
За это сообщение автора поблагодарили: Logger (5), Pokersky09 (2). |
07.11.2018, 21:50 | #4 |
Участник
|
технически у тебя два разных класса: исходный и его расширения. очевидно невозможно перекрывать методы расширений (они ж final) ни в классах наследниках, ни в их, наследниках, расширениях. поэтому, строго говоря, это вообще два разных метода у тебя, несмотря на то, что имена у них одинаковы.
если бы расширение класса-наследника "видело" все добавленные во всех расширениях методы класса-родителя, то потребовалось бы вызывать next. и наоборот, если бы расширенные методы класса-родителя трактовались как "родные", они были бы доступны к перекрытию, но ты не можешь вызвать super во втором методе. так что IS и AS твои друзья тут
__________________
Felix nihil admirari |
|
|
За это сообщение автора поблагодарили: trud (2), malex (1), ax_mct (3). |
08.11.2018, 09:44 | #5 |
Участник
|
Я так и поступил, но надеялся что это был workaround. Придется почти весь код из наследников переносить в родительский классы с кучей кейсов.
PS: Я все таки думал что на уровне своих методов в экстеншенах будет наследование. А то получается мы у себя в МС будем использовать наследование и override, а вы со своими ISV решениями мучайтесь как хотите и плевать что архитектура внутри у вас будет не очень и с кучей дублирования кода. Последний раз редактировалось malex; 08.11.2018 в 09:46. |
|
08.11.2018, 10:51 | #6 |
Moderator
|
Цитата:
Сообщение от malex
Я так и поступил, но надеялся что это был workaround. Придется почти весь код из наследников переносить в родительский классы с кучей кейсов.
PS: Я все таки думал что на уровне своих методов в экстеншенах будет наследование. А то получается мы у себя в МС будем использовать наследование и override, а вы со своими ISV решениями мучайтесь как хотите и плевать что архитектура внутри у вас будет не очень и с кучей дублирования кода. 1. Определить свои классы как наследники inventMov_purch, inventMov_Sales и тп 2. Переопределить с помощью CoC метод inventMovement::constructNoThrow(), так чтобы он возвращал экземпляры своих классов, вместо стандартных ? |
|
08.11.2018, 12:14 | #7 |
Участник
|
Может я глупость скажу, но в исходном примере final class InventMovementAQM_Extension то есть эктеншены это два не связанных между собою типа и добавляют два несвязанных между собой метода. Вы пробовали унаследовать один от другого?
|
|
12.11.2018, 23:31 | #8 |
Участник
|
Макс, это не глупость, а именно то же, что уже сказал я. Раз нас уже двое, то мы не можем ошибаться!
__________________
Felix nihil admirari |
|
13.11.2018, 04:14 | #9 |
Banned
|
Тут кстати есть где сконфьюзиться
Цитата:
the classes that inherit from a class that has extensions inherit the methods that are defined in the extension classes.
Концепция эффективного класса. Причем эта "сборка" еще зависит от включенных моделей. Как я понимаю extension это не про "extend", а про "add". The effective class concept |
|
13.11.2018, 04:19 | #10 |
Banned
|
Важно что это на самом деле class augmentation (приращение) просто они для красного словца используют class extension
Цитата:
The functionality for class extension, or class augmentation,
|
|
13.11.2018, 11:33 | #11 |
Участник
|
Я имел ввиду, что, может, достаточно сделать их наследниками (но, соответственно, получается что от фреймворка требуется соблюдения правила что подкласс вытесняет суперкласс из экстешненов, а соблюдается ли оно, я не знаю)
|
|
19.11.2018, 21:15 | #12 |
Участник
|
как это ты их сделаешь наследниками?
__________________
Felix nihil admirari |
|
20.11.2018, 15:08 | #13 |
Участник
|
Вернее, одного вылечить от бездетности, а второго сделать наследником.
X++: // remove "final" class InventMovementAQM_Extension ... // add "extends" final class InventMov_PurchAQM_Extension extends InventMovementAQM_Extension ... Последний раз редактировалось belugin; 20.11.2018 в 15:09. Причина: Запятые - это важно! |
|
21.11.2018, 00:52 | #14 |
Участник
|
ух ты! а вот у этого, второго, который не стрелял, у него на шапке звезда горит и написано [ExtensionOf(?)] ?
__________________
Felix nihil admirari |
|
21.11.2018, 09:45 | #15 |
Участник
|
Ну да. Сам не пробовал, но интересно, что получится.
|
|
21.11.2018, 17:07 | #16 |
Участник
|
ничего не получится!
любой extension - это final, а final - это кастрат, у которого наследников в принципе не бывает. так что твоя идея по определению неосуществима. воспринимай extension как крюк вместо руки у пирата. сын пирата не родится с крюком никогда. сыну пирата, конечно, тоже можно отрубить руку и приделать крюк, но это будут два разных крюка. пик рилейтед.
__________________
Felix nihil admirari |
|
10.10.2023, 11:37 | #17 |
Участник
|
Решение есть
Прошу прощение за Офтоп, У меня недавно возникла необходимость сделать подобное, и все получилось, не так красиво как я бы хотел но все же:
X++: class A { } class B extends A { } [ExtensionOf(classStr(A))] final class A_Extension { public void salute() { switch (true) { case this is B: B b = this ; b.salute(); default : info("A extension"); } } } [ExtensionOf(classStr(B))] final class B_Extension { public void salute() { info("B extension"); } } |
|
10.10.2023, 11:43 | #18 |
Участник
|
Нет, это не Офтоп.... как то по другому называется
|
|
11.10.2023, 00:43 | #19 |
Administrator
|
Цитата:
Какие в этом случае всплывают проблемы: 1. (Основная). Очевидно, что это работает только для новых методов. Т.е. нельзя в классе А сделать расширение стандартного метода (с использованием метода next), потому что next не позволяет себя вызывать "по условию". Точнее сделать-то можно, вот только когда сделаешь - получается, что можно было сделать проще без этих "выкрутасов". 2. (Организационная). Каждый разработчик должен будет этот "стиль" поддерживать при добавлении нового метода. 3. (Организационная). При наличии нескольких расширений одного класса - они формально могут применяться в любой последовательности. Следовательно код можно писать только такой, который не будет зависеть от последовательности вызова разных расширений. Т.е. да, чисто академически - так можно написать. Но реально претворить это в жизнь.... весьма сложно, а главное - относительно без особой выгоды.
__________________
Возможно сделать все. Вопрос времени |
|
11.10.2023, 11:17 | #20 |
Участник
|
Да, сталкивался с этим. Один и тот же функционал работал в разные моменты по-разному. Оказалось, что именно из-за разной произвольной последовательности работы нескольких расширений.
|
|
Теги |
chain of command, d365fo |
|
|