OK, więc mam nadzieję, że jest to subiektywne pytanie dla programistów, ale proszę bardzo. Nieustannie poszerzam swoją znajomość języków i praktyk inżynierii oprogramowania ... i natknąłem się na coś, co nie ma dla mnie żadnego sensu.
W C ++ deklaracje klas zawierają private:
metody i parametry w pliku nagłówkowym, który teoretycznie przekazuje się użytkownikowi, jeśli zostanie on lib.
W Objective-C @interface
robimy prawie to samo, zmuszając cię do listy prywatnych członków (przynajmniej istnieje sposób na uzyskanie prywatnych metod w pliku implementacji).
Z tego, co mogę powiedzieć, Java i C # pozwalają na zapewnienie interfejsu / protokołu, który może zadeklarować wszystkie publicznie dostępne właściwości / metody i daje koderowi możliwość ukrycia wszystkich szczegółów implementacji w pliku implementacji.
Czemu? Enkapsulacja jest jedną z głównych zasad OOP, dlaczego w C ++ i Obj-C brakuje tej podstawowej umiejętności? Czy istnieje jakiś sprawdzony sposób obejścia Obj-C lub C ++, który ukrywa całą implementację?
Dzięki,
źródło
Odpowiedzi:
Pytanie brzmi, czy kompilator musi wiedzieć, jak duży jest obiekt. Jeśli tak, to kompilator musi wiedzieć o członkach prywatnych, aby je policzyć.
W Javie istnieją pierwotne typy i obiekty, a wszystkie obiekty są przydzielane osobno, a zawierające je zmienne są tak naprawdę wskaźnikami. Dlatego, ponieważ wskaźnik jest obiektem o stałym rozmiarze, kompilator wie, jak dużą rzecz reprezentuje zmienna, nie znając rzeczywistego rozmiaru wskazywanego obiektu. Konstruktor obsługuje to wszystko.
W C ++ można mieć obiekty reprezentowane lokalnie lub na stercie. Dlatego kompilator musi wiedzieć, jak duży jest obiekt, aby mógł przydzielić zmienną lokalną lub tablicę.
Czasami pożądane jest podzielenie funkcjonalności klasy na interfejs publiczny i prywatny wszystko inne, i tam właśnie pojawia się technika PIMPL (Pointer to IMPLementation). Klasa będzie miała wskaźnik do prywatnej klasy implementacyjnej, a metody klasy publicznej mogą wywoływać że.
źródło
Ze względu na konstrukcję C ++, aby utworzyć obiekt na stosie, kompilator musi wiedzieć, jak duży jest. Aby to zrobić, musi mieć wszystkie pola obecne w pliku nagłówka, ponieważ to wszystko, co kompilator może zobaczyć, gdy nagłówek jest dołączony.
Na przykład, jeśli zdefiniujesz klasę
to
sizeof(Foo)
jestsizeof(a) + sizeof(b)
. Jeśli istniał jakiś mechanizm oddzielający pola prywatne, nagłówek może zawieraćz
sizeof(Foo) = sizeof(a) + ???
.Jeśli chcesz naprawdę ukryć prywatne dane, wypróbuj idiom pimpl z
w nagłówku i definicję
FooImpl
tylko wFoo
pliku implementacyjnym.źródło
Wszystko sprowadza się do wyboru projektu.
Jeśli naprawdę chcesz ukryć prywatne szczegóły implementacji klasy C ++ lub Objective-C, to możesz podać jeden lub więcej interfejsów obsługiwanych przez klasę (czysta klasa wirtualna C ++, Objective-C @protocol) i / lub stworzyć klasę potrafi się konstruować, zapewniając statyczną metodę fabryki lub obiekt fabryki klasy.
Powodem, dla którego zmienne prywatne są ujawniane w pliku nagłówkowym / deklaracji klasy / interfejsie @, jest to, że konsument twojej klasy może potrzebować utworzyć jego nową instancję, a a
new MyClass()
lub[[MyClass alloc]init]
w kodzie klienta potrzebuje kompilatora, aby zrozumieć, jak duża jest MyClass Obiekt ma na celu dokonanie przydziału.Java i C # mają również swoje prywatne zmienne wyszczególnione w klasie - nie są wyjątkiem, ale IMO paradygmat interfejsu jest znacznie bardziej powszechny w tych językach. W każdym przypadku możesz nie mieć kodu źródłowego, ale w skompilowanym / bajtowym kodzie jest wystarczająca ilość metadanych, aby wydedukować te informacje. Ponieważ C ++ i Objective-C nie mają tych metadanych, jedyną opcją są rzeczywiste szczegóły interfejsu class / @. W świecie C ++ COM nie ujawniasz prywatnych zmiennych żadnych klas, ale możesz podać plik nagłówkowy - ponieważ klasa jest czysto wirtualna. Obiekt fabryki klasy jest rejestrowany w celu tworzenia rzeczywistych instancji, a niektóre metadane mają różne formy.
W C ++ i Objective-C mniej jest pracy na rozdanie pliku nagłówka w porównaniu do pisania i utrzymywania dodatkowego pliku interfejsu / protokołu. Jest to jeden z powodów, dla których tak często ujawnia się prywatne wdrożenie.
Innym powodem w C ++ są szablony - kompilator musi znać szczegóły klasy, aby wygenerować wersję tej klasy specjalizującą się w podanych parametrach. Wielkość członków klasy różni się w zależności od parametryzacji, więc musi mieć te informacje.
źródło