Czy istnieje różnica między „zmienną instancji” a „właściwością” w Objective-c?

82

Czy istnieje różnica między „zmienną instancji” a „właściwością” w Objective-c?

Nie jestem tego pewien. Myślę, że „właściwość” to zmienna instancji, która ma metody dostępu, ale mogę pomyśleć źle.

Dzięki
źródło

Odpowiedzi:

84

Właściwość jest pojęciem bardziej abstrakcyjnym. Zmienna instancji jest dosłownie tylko miejscem do przechowywania, podobnie jak gniazdo w strukturze. Zwykle inne obiekty nigdy nie mają do nich bezpośredniego dostępu. Z drugiej strony właściwość to atrybut obiektu, do którego można uzyskać dostęp (brzmi niejasno i powinien). Zwykle właściwość zwraca lub ustawia zmienną instancji, ale może używać danych z kilku lub wcale. Na przykład:

@interface Person : NSObject {
    NSString *name;
}

    @property(copy) NSString *name;
    @property(copy) NSString *firstName;
    @property(copy) NSString *lastName;
@end

@implementation Person
    @synthesize name;

    - (NSString *)firstName {
        [[name componentsSeparatedByString:@" "] objectAtIndex:0];
    }
    - (NSString *)lastName {
        [[name componentsSeparatedByString:@" "] lastObject];
    }
    - (NSString *)setFirstName:(NSString *)newName {
        NSArray *nameArray = [name componentsSeparatedByString:@" "];
        NSArray *newNameArray [[NSArray arrayWithObjects:newName, nil] arrayByAddingObjectsFromArray:[nameArray subarrayWithRange:NSMakeRange(1, [nameArray size]-1)]];
        self.name = [newNameArray componentsJoinedByString:@" "];
    }
    - (NSString *)setLastName:(NSString *)newName {
        NSArray *nameArray = [name componentsSeparatedByString:@" "];
        NSArray *newNameArray [[nameArray subarrayWithRange:NSMakeRange(0, [nameArray size]-2)] arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:newName, nil]];
        self.name = [newNameArray componentsJoinedByString:@" "];
    }
@end

(Uwaga: powyższy kod jest błędny, ponieważ zakłada, że ​​nazwa już istnieje i ma co najmniej dwa składniki (np. „Bill Gates” zamiast tylko „Gates”). Czułem, że poprawienie tych założeń uczyniłoby rzeczywisty punkt kodu mniej jasne, więc po prostu wskazuję to tutaj, aby nikt niewinnie nie powtórzył tych błędów.)

Gdakanie
źródło
4
Sposób, w jaki przeglądałem właściwości, jest sposobem zapewniania / ograniczania dostępu do zmiennych instancji dla obiektów zewnętrznych. Coś jak koncepcja publiczno-prywatna w innych językach?
prototypowy
„Normalnie inne obiekty nigdy nie powinny mieć do nich bezpośredniego dostępu”, co masz na myśli? Czy twoja odpowiedź jest również zaktualizowana o nowoczesny Object-C?
Miód
1
@ Kochanie, myślę, że odnosi się do koncepcji hermetyzacji i przestrzegania najlepszych praktyk. Inne obiekty nie powinny mieć bezpośredniego dostępu do ivar ani możliwości jego modyfikacji. Kontrolując dostęp do ivar za pośrednictwem właściwości, możemy przechwycić te wywołania, zanim potencjalnie wpłyną na ivar. Zobacz tutaj, aby uzyskać więcej informacji: en.wikipedia.org/wiki/Encapsulation_(computer_programming)
user3344977
33

Właściwość jest przyjaznym sposobem implementacji metody pobierającej / ustawiającej dla jakiejś wartości, z dodatkowymi użytecznymi funkcjami i składnią. Właściwość może być obsługiwana przez zmienną instancji, ale możesz także zdefiniować metodę pobierającą / ustawiającą, aby wykonywała coś bardziej dynamicznego, np. Możesz zdefiniować właściwość lowerCase w ciągu, który dynamicznie tworzy wynik zamiast zwracać wartość jakiegoś elementu zmienna.

Oto przykład:

// === In your .h ===

@interface MyObject {
    NSString *propertyName;

}

// ...

@property (nonatomic, retain) NSString *propertyName;

// === In your .m @implementation ===

@synthesize propertyName /* = otherVarName */;

@propertyLinia definiuje właściwość o nazwie propertyNametypu NSString *. Można to pobrać / ustawić przy użyciu następującej składni:

myObject.propertyName = @"Hello World!";
NSLog("Value: %@", myObject.propertyName);

Kiedy przypisujesz lub czytasz myObject.propertyName, tak naprawdę wywołujesz metody ustawiające / pobierające na obiekcie.

@synthesizeLinia informuje kompilator do generowania tych getter / ustawiające dla ciebie, stosując zmienną składową o tej samej nazwie obiektu do przechowywania wartości (lub otherVarNamejeśli używasz składni w komentarzach).

Wraz z @synthesizemożesz nadal przesłonić jeden z getter / setters, definiując swój własny. Konwencja nazewnictwa tych metod dotyczy metody setPropertyName:ustawiającej i propertyName(lub getPropertyNamenie jest standardowa) metody pobierającej. Drugi będzie nadal generowany dla Ciebie.

W swoim @propertywierszu możesz zdefiniować wiele atrybutów w parenach dla właściwości, które mogą zautomatyzować takie rzeczy, jak bezpieczeństwo wątków i zarządzanie pamięcią. Domyślnie właściwość jest niepodzielna, co oznacza, że ​​kompilator będzie opakował @synthesizwywołania get / set odpowiednimi blokadami, aby zapobiec problemom ze współbieżnością. Możesz określić nonatomicatrybut, aby to wyłączyć (na przykład na iPhonie, dla którego chcesz domyślnie ustawić większość właściwości nonatomic).

Istnieją 3 wartości atrybutów, które sterują zarządzaniem pamięcią dla dowolnych @synthesizedustawiaczy. Pierwsza to, retainktóra automatycznie wyśle releasedo starych wartości właściwości i retaindo nowych wartości. To jest bardzo przydatne.

Drugi polega na copytym, że utworzy kopię wszelkich przekazanych wartości, zamiast je zachować. Jest to dobra praktyka w copyprzypadku NSString, ponieważ wywołujący może przekazać NSMutableString i zmienić go spod ciebie. copyutworzy nową kopię wejścia, do którego tylko Ty masz dostęp.

Trzeci polega assignna przypisaniu prostego wskaźnika bez wywoływania funkcji retain / release na starym lub nowym obiekcie.

Na koniec możesz również użyć readonlyatrybutu, aby wyłączyć metodę ustawiającą dla właściwości.

Mike Weller
źródło
1
Czy jest jakaś korzyść z zadeklarowania zmiennej instancji i właściwości (np. PropertyName)? Deklaracja wewnątrz interfejsu nie jest potrzebna, jeśli deklarujesz właściwość dla tej samej zmiennej, prawda? To naprawdę oszczędza linijki kodu, chyba że czegoś mi brakuje ...
czemuoz
6

Używam właściwości dla części interfejsu - gdzie obiekt łączy się z innymi obiektami, a zmienne instancji to rzeczy, których potrzebujesz w swojej klasie - nikt oprócz ciebie nie powinien ich widzieć i manipulować nimi.

Jens Busch
źródło
3

Domyślnie właściwość readwrite będzie obsługiwana przez zmienną instancji, która ponownie zostanie automatycznie zsyntetyzowana przez kompilator.

Zmienna instancji to zmienna, która istnieje i zachowuje swoją wartość przez cały okres istnienia obiektu. Pamięć używana dla zmiennych instancji jest alokowana, gdy obiekt jest tworzony po raz pierwszy (poprzez alokację) i zwalniana, gdy obiekt jest zwalniany.

O ile nie określono inaczej, zsyntetyzowana zmienna instancji ma taką samą nazwę jak właściwość, ale z przedrostkiem podkreślenia. Na przykład w przypadku właściwości o nazwie firstName zsyntetyzowana zmienna instancji będzie miała nazwę _firstName.

jitenagarwal19
źródło
2

Wcześniej ludzie używali nieruchomości publicznie, a ivars do użytku prywatnego, ale od kilku lat można również definiować nieruchomości w programie, @implementationaby używać ich prywatnie. Ale nadal używałbym ivars, jeśli to możliwe, ponieważ jest mniej liter do wpisania i zgodnie z tym artykułem działa szybciej . Ma to sens, ponieważ właściwości mają być „ciężkie”: przypuszcza się, że dostęp do nich można uzyskać z wygenerowanych metod pobierających / ustawiających lub zapisanych ręcznie.

Jednak w ostatnich kodach Apple, ivary nie są już używane. Chyba dlatego, że jest bardziej objcniż C/C++plus łatwiej korzystać z właściwości assign, nullableitp

superarts.org
źródło
Domyślam się, że korzystanie z właściwości przez Apple @implementationchce wykazać podobieństwa do Swift. Nadal wolę również zmienne zapasowe, aby nie marnować wywołania funkcji wirtualnej w celu wyszukania prostego pola mojej własnej klasy (a dzieje się tak, gdy uzyskuje się dostęp do właściwości).
Leo