Skládání objektů a dynamické rozpoznání zpráv

Šestý příklad se trochu podobá pátému příkladu; tentokrát si však ukážeme mechanismus, který jednoznačně možnosti vícenásobné dědičnosti přesahuje: připravíme objekt, který bude reprezentovat objekt kterékoli z předem dané skupiny tříd podle potřeby (ale ne všechny najednou).

// Objective C -- příklad 6
//
// ukázka skládání objektů a dynamického rozpoznávání zpráv
// pro služby přesahující možnosti vícenásobné dědičnosti
// -- objekt s dynamicky měnitelnou třídou
// (tento příklad není úplným programem)

// importujeme interface všech tříd, po kterých chceme dědit
#import "Class_1.h"
...
#import "Class_N.h"

@interface DynamicClass: Object
{
id class;
}
@end

@implementation MultipleInheritance
-free
{
int i;

if (class) [class free];
return [self free];
}
-forward:(SEL)msg :(marg_list)parms
{
int i;

// nejprve zjistíme, může-li zpracovat zprávu momentální objekt
if (class)
if ([class respondsTo:msg])
return [class performv:msg:parms];
else class=[class free];
// vyhledáme třídu, jejíž objekty danou zprávu 'umí'
if ([Class_1 instancesRespondTo:msg])
return [class=[Class_1 new] performv:msg:parms];
...
if ([Class_N instancesRespondTo:msg])
return [class=[Class_N new] performv:msg:parms];
// žádná z tříd jež máme k dispozici zprávu nemůže zpracovat ...
// mohli bychom třeba ohlásit chybu, nebo zprávu ignorovat:
return self;
}
@end
// end of file

1. Interface

Properties objektu obsahují pouze jeden odkaz na jeden vnořený objekt. Podobně jako v minulém příkladu nedefinujeme žádné metody, protože objekt žádné vlastní metody neimplementuje: reimplementované metody 'init' a 'free' dědí po třídě Object a všechny ostatní metody přesměruje na vložený objekt.

2. Uvolnění objektu

Metodu 'init' tentokrát není zapotřebí reimplementovat; proto se podíváme rovnou na reimplementaci metody 'free'. Ta je velmi jednoduchá -- jestliže náš objekt obsahuje některý vnořený objekt ('if (class)'), vložený objekt uvolníme; pak objekt uvolní sám sebe voláním '[super free]'.

Opět bychom snadno mohli před uvolněním vloženého objektu ještě provést jakoukoli jeho potřebnou 'deinicializaci' (uložení dat do souboru apod.).

4. Dynamické rozpoznání zpráv

Pro dynamické rozpoznání zpráv samozřejmě opět použijeme zprávu 'forward::'. Její implementace je však tentokrát složitější:

Nejprve zjistíme, obsahuje-li již náš objekt nějaký vnořený objekt a ano-li, ověříme může-li vložený objekt zpracovat zprávu, která právě přišla. Jestliže ji vložený objekt zpracovat může, prostě ji přesměrujeme pomocí známě standardní metody 'performv::' a jsme hotovi; jestliže vložený objekt zprávu zpracovat neumí, uvolníme jej a pokračujeme dále. Povšimněme si výrazu 'class=[class free]' -- jeho pomocí objekt uvolníme a zároveň nulujeme proměnnou 'class', protože metoda 'free' standardně vrací hodnotu 'nil'.

V druhém kroku projdeme všechny třídy; každé z nich se optáme pomocí standardní metody 'instancesRespondTo:' zda její objekty jsou schopny zpracovat zadanou zprávu. Jakmile narazíme na třídu u které je tomu tak, vytvoříme její objekt a zprávu mu přesměrujeme.

Seznam tříd je v tomto případě pro zjednodušení příkladu statický; vzhledem k tomu, že třída je v Objective C objekt jako každý jiný bychom mohli snadno implementovat dynamický seznam tříd, který by se mohl měnit v průběhu života objektu.



(obsah)


Copyright (c) Ondra Čada