Při přípravě jiného článku jsem narazil na dost…
osobité chování Axapty při implementaci rozhraní. Navzdory veškerým očekáváním Axapta nekontroluje, zda má implementující třída správné
veřejné rozhraní (proto
interface), ale jen že má metody
shodných názvů, jaké má i rozhraní.
Ukažme si to na příkladu. Definuji následující rozhraní:
interface Rozhrani
{
int rychlost(int _rychlost){}
}
Předpokládal bych, že každá třída implementující toto rozhraní musí obsahovat metodu
rychlost()
s parametrem a návratovou hodnotou typu
int
.
Následující třída jde nejen zkompilovat, ale kód v metodě
main()
i bez chyby proběhne, včetně přiřazení do proměnné.
class ImplementujiciTrida implements Rozhrani
{
//Správný název metody, ale nesprávný typ parametru i návratové hodnoty
void rychlost(str _slovniPopisRychlosti)
{}
public static void main(Args _args)
{
Rozhrani trida = new ImplementujiciTrida();
//Instance nemá metodu akceptující číselný parameter a vracející hodnotu,
//přesto toto volání proběhně.
int i = trida.rychlost(5);
}
}
Metoda
rychlost()
obdrží hodnotu překonvertovanou do řetězce a vrátí hodnotu 0 (případná hodnota v proměnné i v
main()
by byla přepsána), přestože má návratový typ
void
.
Pokud by implementace metody
rychlost()
obsahovala parametr, pro který neexistuje implicitní konverze (např.
Object _o
), dojde k chybě za běhu aplikace.
Rozhraní má poskytnout jistotu, že instance každé implementující třídy "rozumí" určitému způsobu komunikace, tedy že je možné zavolat nějakou metodu s předem danými typy parametrů. Když se třída hlásí k určitému veřejnému rozhraní (= implementuje interface), kompilátor by měl zajistit, že tomu tak skutečně je. Kompilátor Axapty to ale nedělá - a výsledkem chyby, kterou měla odhalit první kompilace, může být runtime exception nebo opravdu nepochopitelné chování aplikace.
Tímto nechci říct, že se v X++ nemají rozhraní používat. Naopak si myslím, že se používají málo (a místo nich se vytváří sporné hierarchie dědičnosti apod.). Ale nelze se spoléhat na kompilátor, že korektní implementaci rozhraní vynutí.