Okna – cz. 1

Dziś przyszedł czas na opakowanie widgetów w strukturę nadrzędną – okno.

Dotychczas widgety, które tworzyliśmy żyły własnym życiem, zawieszone “gdzieś w przestrzeni”. Ot rysowaliśmy je na ekranie i tyle. Należy jednak pamiętać, iż tworzone przez nas urządzenie musi udostępniać kilkadziesiąt różnych widoków – okien. Ponieważ przy tej skali “ręczna” obsługa widgetów jest mało efektywna i bardzo pracochłonna, najlepszym rozwiązaniem jest delegowanie odpowiedzialności za ich rysowanie do obiektu nadrzędnego.

W ten sposób wymuszamy powstanie ogólnej implementacji “abstrakcyjnego” okna, którego zadaniem będzie narysowanie wszystkich należących do niego widgetów. Analogiczne do widgetu, okno również będzie posiadać uogólniony interfejs w postaci funkcji ZbudujOkno() oraz NarysujOkno(). Widzimy tu pewne podobieństwo w podejściu oraz abstrakcję, pozwalającą odwoływać się z poziomu GUI w ten sam sposób do przeróżnych rodzajów okien.

A może okno powinno być widgetem! Wystarczy, że będzie dziedziczyć…

Stop! A czy okno jest rodzajem widgetu? Nie, okno to zupełnie odrębny byt, który może jedynie zawierać widgety. Cały jego świat rządzi się już innymi prawami! Przekładając to na język developerów – okno nie powinno dziedziczyć niczego po widgecie.

Celowo wybrałem ten przykład, aby pokazać błąd często popełniany zarówno przez mniej jak i bardziej doświadczonych programistów. Polega on na wykorzystywaniu dziedziczenia w stosunku do klas, które powinny być jedynie obiektami składowymi tworzonej klasy. Zawsze należy bowiem zadać sobie pytanie, czy nowo tworzona klasa stanowi rodzaj innej klasy czy po prostu zawiera ją w sobie. To daje jasną odpowiedź, którą drogą pójść.

Ale w zasadzie nie ma to przecież większego znaczenia? W obu przypadkach mamy dostęp do metod i składowych.

Różnica jest i to przeogromna! Czy Opona jest składową Samochodu, czy może Samochód jest rodzajem Opony 🙂 ? Wyobraźmy sobie co by było, gdyby nasz Samochód odziedziczył po Oponie interfejs z metodą Napompuj()🙂

Ok, nasze okno powinno więc zawierać widgety… Ale jak efektywnie przypisać całą chmurę przeróżnych widgetów do okna? Tablica? A może lista?

Jak pamiętamy, na samym początku stworzyliśmy widget typu Box. Jedynym jego zadaniem było grupowanie innych widgetów. Wystarczy nasze abstrakcyjne okno wyposażyć w jeden taki widget, jako element składowy, a następnie przypisać do niego pozostałe widgety – w tym również np. inne Box’y. W ten sposób zachowana zostaje hierarchia widgetów w obrębie okna – korzeniem drzewa kontrolek będzie właśnie ów nadrzędy Box. Nie musimy również tworzyć odrębnego mechanizmu obsługującego widgety z poziomu okna.

Tyle na dziś – z konieczności dzisiejsze rozważania były nieco krótsze 🙂 Jutro kontynuacja, jednak w nieco bardziej praktycznym ujęciu.

Posted in Sto dni w kolorze.