wstęp
Na potrzeby wszystkich wpisów z tej serii zdecydowałem się, w miarę możliwości, skupić je wokół jednego przykładu. Oczywiście nie będę przeprowadzał żadnej analizy wymagań, ani specjalnie rozwodził się nad całą strukturą i pełną funkcjonalnością, będę poruszał jedynie te aspekty aplikacji, które będą bezpośrednio powiązane z danym wpisem. Dzięki takiemu praktycznemu przykładowi mam nadzieję, że uda mi się przedstawić myślenie, które kryje się za większością decyzji projektowych oraz pozbędę się zbędnego teoretyzowania i przykładów, które nijak nie pokrywają się z rzeczywistością.Dzisiaj chciałbym skupić się na atrybutach klasy, więc na początek trochę teorii.
let's start
Atrybuty klasy są czymś, co odróżnia od siebie jej konkretne instancje, umożliwiają one identyfikację obiektów.Można podzielić je na dwa rodzaje:
- typów podstawowych: boolean, string, integer, float
- obiekty, które realizowane są jako agregacja, częściowa lub całkowita (kompozycja)
Atrybuty typów podstawowych są to dane bezpośrednio dotyczące instancji obiektu, natomiast agregacje są to swego rodzaju jego części składowe np. atrybutem budynku jest jego wysokość (typ podstawowy), budynek jednak zawiera też pewną ilość mieszkań (obiekty).Agregację dodatkowo można podzielić na:
- częściowa - oznacza to mniej więcej tyle, że zawieranie nie jest konieczne dla istnienia obiektu głównego i zawieranego np. jabłko zawiera robaka (i jabłko i robak mogą sobie spokojnie istnieć bez siebie:)
- kompozycja - oznacza to, że obiekty składowe nie mogą istnieć bez obiektu głównego ani nie mogą być współdzielone z innymi obiektami. Zostają one usunięta wraz z obiektem głównym np. blok z mieszkaniami.
a gdzie array?
Może niektórzy z Was zwrócili uwagę, że wypisując dwa rodzaje atrybutów, nie uwzględniłem tam typu array. Dlaczego? Ponieważ tablica jest po prostu zbiorem innych typów. Jeżeli tworzymy klasę powinniśmy zadbać o to, aby atrybut, który jest tablicą składał się z elementów tylko jednego typu. Rozumiem, że w dokumentacji PHP często można się spotkać z 'typem' mixed, ale u Was nie powinno być dla niego miejsca. Co jeżeli jednak tablica okazuje się zawierać różne typy i nijak nie da się tego inaczej zrobić? Może to oznaczać dwie rzeczy:
- należy utworzyć klasę, a elementy tablicy powinny być jej atrybutami. Oczywiście to rozwiązanie można zastosować tylko wtedy, gdy taka klasa będzie posiadała logiczny sens
- należy usiąść do projektu jeszcze raz i zastanowić się, gdzie jest błąd:)
widoczność atrybutów
Ogólnie jestem zdania, że każdy atrybut klasy powinnien być prywatny. W końcu jednym z głównych paradygmatów progamowania obiektowego jest
hermetyzacja, co wyraźnie mówi, że nie powinno się udostępniać swoich wnętrzości światu. Stosowanie atrybutów chronionych, jeżeli wiemy, że klasa będzie rozszerzana? Takie coś również do mnie nie przemawia, wolę stworzyć chroniony getter i/lub setter, a atrybut i tak zostawić prywatny, nawet jeżeli jest to klasa abstrakcyjna. Ale to już moje osobiste zdanie i niejedną dyskusję na ten temat toczyłem i wiem, że w takich przypadkach wielu programistów stosuje jednak atrybut protected.A co z atrybutami publicznymi? Coś takiego byłbym w stanie zrozumieć, jeżeli miałbym klasę z x liczbą atrybutów, która wymagałaby setterów i getterów dla każdego z nich. W takim wypadku rzeczywiście rozsądniej byłoby uczynić je publicznymi. Jednak w czasie swojej kariery programisty nigdy nie spotkałem się z sytuacją, aby obiekt wymagał osobnego gettera i settera dla każdego atrybutu i ciężko mi wyobrazić sobie, aby taka funkcjonalność mogła mieć jakieś logiczne uzasadnienie.
nie mieszaj typów
Zdaję sobię sprawę, że PHP umożliwia przypisywanie do jednej zmiennej wartości różnych typów, ale jest to coś, czego nie powinno się robić, a już z pewnością nie w odniesieniu do atrybutów klas. Jeżeli mam jakiś atrybut typu string, to powinnien on być tego typu, nie integer, float, czy object, a tylko i wyłącznie string. Wiem, że dla wielu to oczywiste, ale mimo wszystko...
odrobina praktyki
Załóżmy, że naszym zadaniem jest stworzenie systemu dla firmy transportowej. Jednym z głównych części składowych ma być baza kontrahentów. Przy dodawaniu kontrahenta użytkownik musi określić jego NIP oraz unikalną nazwę. Musi istnieć możliwość wystawiania i przesyłania drogą mailową faktur za usługi firmy oraz musi być możliwość wykonania przelewu na konto kontrahenta, z którego usług korzystała firma. Firma jest międzynarodowa, więć musi istnieć możliwość obsługi różnych walut. Niektórzy kontrahenci mają kilka osób, do których chcą aby były wysyłane faktury na maila. Dodatkowo powinna istnieć możliwość określenia adresu siedziby kontraheta.Na podstawie powyższego spróbujmy określić atrybuty dla klasy kontrahent.Pierwszą rzeczą, którą wiemy jest to, że kotrahent musi posiadać NIP i nazwę:
<?phpclass Contractor { private $_nip; //string private $_name; //string}
Kontrahent może posiadać wiele kont przypisanych do przelewów w różnych walutach. Ponieważ numer konta i waluta są ściśle ze sobą powiązane decydujemy się na utworzenie kolejnej klasy reprezentującej konto bankowe:
<?phpclass BankAccount{ private $_number; //string private $_currency; //string}class Contractor { private $_nip; //string private $_name; //string private $_bankAccounts; //BankAccount[]}
Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Zwiń
Czytaj na blogu autora...