Gratulacje! Właśnie okrążyłeś globus systemu / języka programowania, przybywając na drugą stronę świata, skąd odszedłeś. Właśnie wylądowałeś na granicy dynamicznego obiektu opartego na języku / prototypie!
Wiele języków dynamicznych (np. JavaScript, PHP, Python) umożliwia rozszerzenie lub zmianę właściwości obiektu w czasie wykonywania.
Skrajną formą tego jest język oparty na prototypach, taki jak Self lub JavaScript. Nie mają zajęć, ściśle mówiąc. Możesz robić rzeczy, które wyglądają jak oparte na klasach, obiektowe programowanie z dziedziczeniem, ale reguły są znacznie bardziej rozluźnione w porównaniu do ostrzej zdefiniowanych języków opartych na klasach, takich jak Java i C #.
Langauges, takie jak PHP i Python, żyją pośrodku. Mają regularne, idiomatyczne systemy oparte na klasach. Ale atrybuty obiektów mogą być dodawane, zmieniane lub usuwane w czasie wykonywania - aczkolwiek z pewnymi ograniczeniami (takimi jak „oprócz typów wbudowanych”), których nie można znaleźć w JavaScript.
Dużym kompromisem dla tego dynamizmu jest wydajność. Zapomnij, jak mocno lub słabo wpisany jest język lub jak dobrze można go skompilować do kodu maszynowego. Obiekty dynamiczne muszą być reprezentowane jako elastyczne mapy / słowniki, a nie proste struktury. Zwiększa to dostęp do każdego obiektu. Niektóre programy dokładają wszelkich starań, aby zmniejszyć ten narzut (np. Z przypisywaniem kwantowego kwarga i klasami opartymi na slotach w Pythonie), ale dodatkowy narzut jest zwykle równy kursowi i cenie wstępu.
Wracając do swojego projektu, przeszczepiasz zdolność posiadania dynamicznych właściwości na podzbiorze swoich klas. A Productmoże mieć zmienne atrybuty; przypuszczalnie tak Invoiceczy Ordernie i nie mógł. To nie jest zła droga. Daje ci elastyczność, aby mieć zmienne tam, gdzie jest to potrzebne, pozostając w ścisłym, zdyscyplinowanym języku i systemie pisma. Z drugiej strony jesteś odpowiedzialny za zarządzanie tymi elastycznymi właściwościami i prawdopodobnie będziesz musiał to zrobić za pomocą mechanizmów, które wyglądają nieco inaczej niż bardziej natywne atrybuty. p.prop('tensile_strength')zamiast p.tensile_strengthna przykład i p.set_prop('tensile_strength', 104.4)raczej niżp.tensile_strength = 104.4. Ale pracowałem z wieloma programami w Pascal, Ada, C, Java, a nawet w językach dynamicznych, i korzystałem z nich, a także korzystałem z takiego dostępu do getter-setter dla niestandardowych typów atrybutów; podejście jest wyraźnie wykonalne.
Nawiasem mówiąc, napięcie między typami statycznymi a bardzo zróżnicowanym światem jest niezwykle powszechne. Analogiczny problem często pojawia się podczas projektowania schematu bazy danych, szczególnie w relacyjnych i przed relacyjnych magazynach danych. Czasami rozwiązuje się to poprzez tworzenie „superrzędów”, które zawierają wystarczającą elastyczność, aby pomieścić lub zdefiniować połączenie wszystkich wymyślonych odmian, a następnie upchnąć dane, które pojawią się w tych polach. WordPress wp_postsstół , na przykład, ma pola, na przykład comment_count, ping_status, post_parenti post_date_gmtże są tylko interesujące w pewnych okolicznościach, i że w praktyce często wygaszony. Innym podejściem jest bardzo oszczędny, znormalizowany stół wp_optionspodobny do twojegoPropertyklasa. Chociaż wymaga to bardziej precyzyjnego zarządzania, elementy w nim rzadko są puste. Zorientowane obiektowo i dokumentacyjne bazy danych (np. MongoDB) często łatwiej radzą sobie ze zmianą opcji, ponieważ mogą tworzyć i ustawiać atrybuty praktycznie do woli.