Odkąd zacząłem pracować nad aplikacjami na iOS i celem C, byłem naprawdę zaskoczony różnymi lokalizacjami, w których można deklarować i definiować zmienne. Z jednej strony mamy tradycyjne podejście C, z drugiej mamy nowe dyrektywy ObjectiveC, które dodają do tego OO. Czy moglibyście pomóc mi zrozumieć najlepsze praktyki i sytuacje, w których chciałbym użyć tych lokalizacji dla moich zmiennych i być może poprawić swoje obecne rozumienie?
Oto przykładowa klasa (.h i .m):
#import <Foundation/Foundation.h>
// 1) What do I declare here?
@interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
// 3) class-specific method / property declarations
@end
i
#import "SampleClass.h"
// 4) what goes here?
@interface SampleClass()
// 5) private interface, can define private methods and properties here
@end
@implementation SampleClass
{
// 6) define ivars
}
// 7) define methods and synthesize properties from both public and private
// interfaces
@end
- Rozumiem 1 i 4, że są to deklaracje i definicje oparte na plikach w stylu C, które w ogóle nie rozumieją pojęcia klasy, a zatem muszą być używane dokładnie tak, jak byłyby używane w C. Widziałem je używany do implementowania statycznych singletonów opartych na zmiennych wcześniej. Czy brakuje mi innych wygodnych zastosowań?
- Moje wnioski z pracy z iOS są takie, że ivars zostały prawie całkowicie wycofane poza dyrektywą @synthesize i dlatego mogą być w większości ignorowane. Czy tak jest?
- Odnośnie 5: dlaczego miałbym kiedykolwiek chcieć deklarować metody w prywatnych interfejsach? Moje metody klasy prywatnej wydają się dobrze kompilować bez deklaracji w interfejsie. Czy chodzi głównie o czytelność?
Wielkie dzięki, ludzie!
źródło
Najpierw przeczytaj odpowiedź @ DrummerB. To dobry przegląd powodów i tego, co ogólnie powinieneś robić. Mając to na uwadze, odpowiadając na konkretne pytania:
Nie ma tu żadnych definicji zmiennych (jest to technicznie legalne, jeśli wiesz dokładnie, co robisz, ale nigdy tego nie rób). Możesz zdefiniować kilka innych rodzajów rzeczy:
Extern wyglądają jak deklaracje zmiennych, ale są po prostu obietnicą zadeklarowania ich w innym miejscu. W ObjC powinny być używane tylko do deklarowania stałych i ogólnie tylko stałych łańcuchowych. Na przykład:
Następnie w swoim
.m
pliku zadeklarowałbyś rzeczywistą stałą:Jak zauważył DrummerB, jest to dziedzictwo. Nie umieszczaj niczego tutaj.
Tak.
Stałe zewnętrzne, jak opisano powyżej. Tutaj można również zapisać zmienne statyczne. Są to odpowiedniki zmiennych klasowych w innych językach.
tak
Ale bardzo rzadko. Prawie zawsze powinieneś pozwolić clang (Xcode) na tworzenie zmiennych za Ciebie. Wyjątki dotyczą zwykle modułów ivar innych niż ObjC (takich jak obiekty Core Foundation, a zwłaszcza obiekty C ++, jeśli jest to klasa ObjC ++) lub ivary, które mają dziwną semantykę pamięci (jak ivary, które z jakiegoś powodu nie pasują do właściwości).
Generalnie nie powinieneś już @synthesize. Clang (Xcode) zrobi to za Ciebie i powinieneś na to pozwolić.
W ciągu ostatnich kilku lat sprawy znacznie się uprościły. Efektem ubocznym jest to, że istnieją teraz trzy różne epoki (Fragile ABI, Non-fragile ABI, Non-fragile ABI + auto-syntheisze). Więc kiedy zobaczysz starszy kod, może to być trochę zagmatwane. Stąd zamieszanie wynikające z prostoty: D.
źródło
Jestem też całkiem nowy, więc mam nadzieję, że niczego nie schrzanię.
1 i 4: Zmienne globalne w stylu C: mają zakres obejmujący cały plik. Różnica między nimi polega na tym, że ponieważ mają one szerokość pliku, pierwsza będzie dostępna dla każdego, kto importuje nagłówek, a druga nie.
2: zmienne instancji. Większość zmiennych instancji jest syntetyzowana i pobierana / ustawiana za pomocą metod dostępu przy użyciu właściwości, ponieważ sprawia, że zarządzanie pamięcią jest przyjemne i proste, a także zapewnia łatwą do zrozumienia notację kropkową.
6: Ivars implementacji są nieco nowe. To dobre miejsce na umieszczenie prywatnych ivarów, ponieważ chcesz ujawnić tylko to, co jest potrzebne w publicznym nagłówku, ale podklasy nie dziedziczą ich AFAIK.
3 i 7: Publiczne deklaracje metod i właściwości, a następnie implementacje.
5: Prywatny interfejs. Zawsze używam prywatnych interfejsów, kiedy tylko mogę, aby zachować porządek i stworzyć rodzaj efektu czarnej skrzynki. Jeśli nie muszą o tym wiedzieć, umieść to tam. Robię to również dla czytelności, nie wiem, czy są jakieś inne powody.
źródło
To jest przykład wszystkich rodzajów zmiennych zadeklarowanych w Objective-C. Nazwa zmiennej wskazuje na jej dostęp.
Plik: Animal.h
Plik: Animal.m
Zwróć uwagę, że zmienne iNotVisible nie są widoczne z żadnej innej klasy. Jest to problem z widocznością, więc zadeklarowanie ich z
@property
lub@public
nie zmienia tego.Wewnątrz konstruktora dobrą praktyką jest uzyskiwanie dostępu do zmiennych zadeklarowanych za
@property
pomocą podkreślenia zamiast tego,self
aby uniknąć skutków ubocznych.Spróbujmy uzyskać dostęp do zmiennych.
Plik: Cow.h
Plik: Krowa. M
Nadal możemy uzyskać dostęp do niewidocznych zmiennych za pomocą środowiska uruchomieniowego.
Plik: Cow.m (część 2)
Spróbujmy uzyskać dostęp do niewidocznych zmiennych.
Plik: main.m
To drukuje
Zauważ, że udało mi się uzyskać dostęp do zaplecza ivar,
_iNotVisible2
które jest prywatne dla podklasy. W Objective-C można odczytać lub ustawić wszystkie zmienne, nawet te, które są zaznaczone@private
, bez wyjątków.Nie uwzględniłem powiązanych obiektów ani zmiennych C, ponieważ są to różne ptaki. Jeśli chodzi o zmienne C, każda zmienna zdefiniowana na zewnątrz
@interface X{}
lub@implementation X{}
jest zmienną C o zasięgu pliku i pamięci statycznej.Nie omawiałem atrybutów zarządzania pamięcią ani atrybutów tylko do odczytu / odczytu, pobierania / ustawiania.
źródło