Statický přístup k objektům
Tentokrát se seznámíme s podporou, kterou Objective C nabízí pro statické neobjektové programování.
Zamysleme se nejprve nad tím, jaký má smysl statické programování využívat. Na první pohled je místo statického programování tam, kde potřebujeme dosáhnout maximální paměťové a/nebo časové efektivity. Implementace objektových mechanismů je však velmi efektivní sama o sobě; operační systém NeXTstep například s výhodou používá objektové mechanismy i pro implementaci ovladačů periferních zařízení. Zbývá tedy snad jen jediný typ programů, které má smysl psát neobjektově: viry...
// Objective C -- příklad 8
//
// příklad statického přístupu k objektům
#import <stdio.h>
#import <string.h>
#import <objc/Object.h>
@interface Test:Object
{
| @public | // proměnná i je k dispozici pro statický přístup |
| } | |
| -(int)getI; |
-setI:(int)val;
@end
@implementation Test
-(int)getI { return i; }
-setI:(int)val { i=val; return self; }
@end
void main()
{
// proměnná 'x' má stejnou strukturu jako objekt třídy Test:
struct {
@defs(Test);
} x;
Test *test=[Test new];
IMP seti,geti;
int i;
// můžeme např. kopírovat data mezi objektem a 'stejnou' proměnnou:
[test setI:333];
memcpy(&x,test,sizeof(x));
printf("333=%d\n",x.i);
// proměnná i objektu text je deklarována po direktivě @public;
// můžeme k ní proto přistupovat přímo
#ifdef STATIC_ACCESS
for (i=0;i<1000000;i++)
test->i=test->i+1;
#else
for (i=0;i<1000000;i++)
[test setI:[test getI]+1];
#endif
printf("%d=%d\n",test->i,[test getI]);
// chceme-li, můžeme získat ukazatel na metodu a volat ji jako funkci;
// musíme přitom jako první a druhý parametr uvést objekt, který má
// funkci zpracovat a zprávu, která se zpracovává
#ifdef STATIC_ACCESS
seti=[test methodFor:@selector(setI:)];
geti=[test methodFor:@selector(getI)];
for (i=0;i<1000000;i++)
seti(test,@selector(setI:),(int)geti(test,@selector(getI))+1);
#else
// 'Objektově' bychom mohli příklad přeprogramovat takto:
for (i=0;i<1000000;i++)
[test setI:[test getI]+1];
#endif
printf("Hotovo (%d)\n",[test getI]);
[test free];
}
// end of file
Zdrojový kód příkladu by už měl být čtenářům našeho seriálu zřejmý; namísto jeho podrobného popisu proto ukážeme časový rozdíl mezi objektovým a neobjektovým přístupem:
localhost> cc -Wall -DSTATIC_ACCESS sample8.m
localhost> /bin/time a.out
333=333
1000333=1000333
Hotovo (2000333)
2.1 real 1.7 user 0.0 sys
localhost> cc -Wall sample8.m
sample8.m: In function `main':
sample8.m:29: warning: unused variable `geti'
sample8.m:29: warning: unused variable `seti'
localhost> /bin/time a.out
333=333
1000333=1000333
Hotovo (2000333)
5.2 real 4.8 user 0.0 sys
localhost>
Vidíme, že s využitím objektových technik se program, který nedělá téměř nic jiného než předávání zpráv, oproti statickému mechanismu zpomalí trochu více než dvakrát. To je ve všech běžných programech -- které samozřejmě dělají moho jiných věcí, takže zpomalení bude daleko menší -- velmi dobrá cena za všechny výhody objektového programování a pozdní vazby.