Obsługa właściwości tablicowych w klasie z użyciem "metod magicznych" |
Obsługa właściwości tablicowych w klasie z użyciem "metod magicznych" |
3.11.2017, 00:16:45
Post
#1
|
|
Grupa: Zarejestrowani Postów: 2 Pomógł: 0 Dołączył: 2.11.2017 Ostrzeżenie: (0%) |
Witam
Czy w PHP jest możliwy dostęp w klasie do prywatnego pola będącego tablicą, za pomocą tzw. „metod magicznych” __get i __set? Pytam, ponieważ używam wymienionych metod do uzyskiwania dostępu do pól klasy, które są typami prostymi lub obiektami i to działa całkiem przyzwoicie (wiem, że są pewne spadki wydajności ale to w chwili obecnej nie jest dla mnie kluczowe). Chciałbym niektóre utworzone przez siebie klasy wyposażyć we właściwości tablicowe. Przez pojęcie właściwości rozumiem tu mechanizm znany z języków takich jak C# czy ObjectPascal, gdzie w klasie istnieje pole, do którego dostęp odbywa się poprzez prywatne metody dostępowe (akcesory). Pozwala to np.: sprawdzać poprawność przekazywanych wartości (dla metody „set”) czy zwracać określoną wartość dla właściwości, która może nie posiadać odpowiadającego jej prywatnego pola w klasie a zwracana wartość jest np. obliczana (dla metody „get”). Żeby dobrze wyłuszczyć nurtujący mnie problem, przytoczę fragment hipotetycznej klasy:
Dostęp do dwóch pierwszych pól w utworzonym obiekcie wyżej podanej klasy jest dość wygodny, np.:
Niestety do pola $_values można dostać się tylko przy jawnym wywołaniu metod getValues i setValues, np.:
Czy w PHP jest możliwe takie przebudowanie wyżej podanego ciągu instrukcji metod __get i __set aby można było dostać się do pola $_values w taki sposób:
Wg mojej wiedzy dotyczącej PHP (z pewnością niekompletnej), tego nie da się zaimplementować. A to dlatego, ponieważ metoda magiczna __get pobiera tylko jeden argument, którym jest nazwa właściwości. Niestety nie da się przekazać indeksu komórki do tablicy. Podobnie ma się rzecz z metodą magiczną __set, która pobiera tylko dwa argumenty, którymi są nazwa właściwości i wartość podlegająca przypisaniu do prywatnego pola. Być może się mylę i da się ten problem rozwiązać (co byłoby miłym zaskoczeniem). Rzecz jednak w tym, że dość skrupulatnie przekopywałem dział Help serwisu php.net. Próbowałem także przeszukiwać różne fora i blogi dotyczące programowania w PHP. Niestety nie natknąłem się na rozwiązanie takiego problemu. Jedyne na co trafiłem to na propozycje rozszerzenia języka PHP o metody dostępowe get i set działające podobnie jak w C# (tu: https://bugs.php.net/bug.php?id=49526, ale ta propozycja została odrzucona a szkoda, bo ten mechanizm wydaje się być o wiele lepszy niż tzw. "metody magiczne"). Czy jest zatem możliwe obsłużenie w klasie prywatnego pola-tablicy za pomocą metod magicznych __get i __set? |
|
|
3.11.2017, 00:56:11
Post
#2
|
|
Grupa: Zarejestrowani Postów: 556 Pomógł: 40 Dołączył: 20.07.2012 Skąd: Warszawa Ostrzeżenie: (0%) |
Ten post edytował kayman 3.11.2017, 01:08:03 |
|
|
5.11.2017, 19:39:43
Post
#3
|
|
Grupa: Zarejestrowani Postów: 2 Pomógł: 0 Dołączył: 2.11.2017 Ostrzeżenie: (0%) |
Szanowny kayman'ie Twoja odpowiedź niestety nie dotyka istoty opisanego przez mnie problemu. Przykład podany przez Ciebie jest bardzo popularny. Nie chodziło mi o banalny/trywialny sposób dostępu do pól klasy zgromadzonych w jednym polu jako tablicy, indeksowanej nazwami właściwości. Jeszcze raz powtórzę: jedno z pól klasy jest tablicą. Być może nieporozumienie wynika z tego, że w dokumentacji PHP występuje pojęcie właściwości, które jest błędnie użyte przez ludzi rozwijających język PHP. To co oni opisują w swoim systemie pomocy jako właściwość to jest w rzeczywistości polem klasy. Właściwości to mechanizm dostępu do pól klasy przez metody dostępowe, które są wywoływane niejawnie (nie jest to ścisła definicja, a tylko mój jak najkrótszy opis).
Ja w swoich klasach potrzebuję dostępu do komórek pola będącego tablicą w klasie, poprzez symulowanie właściwości, które by pozwalały przekazywać indeks komórki w metodach __get i __set. W językach, które wymieniłem w poprzednim poście, tj. C# czy ObjectPascal właściwości mogą być tablicowe. Oznacza to, że w tych językach metody dostępowe "get" i "set" uwzględniają dodatkowy parametr, którym jest indeks. Przykładowo w języku ObjectPascal, klasa którą w pierwszym poście przedstawiłem, miałaby następujący (zbliżony do PHP) kod: Kod TMyComponent = class(TObject) private FCount: Integer; FName: String; FValues: TList<TPerson>; function GetValue(const Index: Integer): TPerson; procedure SetName(Value: String); procedure SetValue(const Index: Integer; Value: TPerson); public constructor Create; destructor Destroy; override; property Count: Integer read FCount; property Name: Integer read FName write SetName; property Values[const Index: Integer]: TPerson read GetValue write SetValue; end; constructor Create; begin FCount := 0; FName := ""; FValues := TList<TPerson>.Create; end; destructor Destroy; begin FValues.Free; inherited Destroy; end; function SetName; begin if (FName <> Value) then FName := Value; end; function GetValue(const Index: Integer): TPerson; begin Result := nil; if IsIndexValid(Index) then Result := FValues[Index]; end; procedure SetValue(const Index: Integer; Value: TPerson); begin if IsIndexValid(Index) then FValues[Index] := Value; end; function IsIndexValid(const Index: Integer); begin Result := (Index >= 0) and (Index < FValue.Count); end; ... // i sposób jej użycia myObj := TMyComponent.Create; ... var OldValue: Integer; ... OldValue := myObj.Values[2]; // odczyt właściwości tablicowej myObj.Values[2] := 64; // zapis właściwości tablicowej ... myObj.Free; To co ja bym potrzebował, można by przedstawić za pomocą następującego hipotetycznego (całkiem wymyślonego) kodu w PHP:
Wtedy wyżej przedstawioną hipotetyczną klasę używałoby się następująco (na razie też wyłącznie hipotetycznie :-)
W tym hipotetycznym kodzie metod __get i __set widać, że posiadają one dodatkowy opcjonalny parametr, który służy do przekazywania indeksu do tablicy. I wg mojej wiedzy w PHP takiej możliwości nie ma, bo metoda __get przyjmuje jeden parametr (nazwę pola w klasie) a metoda __set dwa parametry (nazwę pola w klasie i wartość do zapisania w tym polu). Nie ma możliwości przekazania indeksów dla pól będących tablicami. A tego mi właśnie bardzo brakuje. Na razie zostaje mi obsługa dostępu do pól w klasach na modłę języka Java, tj. poprzez publiczne metody dostępowe, co jest trochę upierdliwe. Chyba, że jednak da się w kodzie PHP jakoś przekazać do metod __get i __set dodatkowy parametr a tylko ja o tym nie wiem. Bardzo by mnie to ucieszyło, usprawniłbym swoją "biblioteczkę" klas. |
|
|
Wersja Lo-Fi | Aktualny czas: 26.09.2024 - 04:49 |