Objective-c'deki "örnek değişkeni" ile "özellik" arasında bir fark var mı?


82

Objective-c'de "örnek değişkeni" ile "özellik" arasında bir fark var mı?

Bundan pek emin değilim. Bir "özelliğin" erişimci yöntemlere sahip bir örnek değişkeni olduğunu düşünüyorum, ancak yanlış düşünebilirim.

Yanıtlar:


84

Mülk, daha soyut bir kavramdır. Bir örnek değişkeni, bir yapıdaki bir yuva gibi, kelimenin tam anlamıyla yalnızca bir depolama yuvasıdır. Normalde diğer nesnelerin bunlara doğrudan erişmesi beklenmez. Öte yandan, bir özellik, erişilebilen nesnenizin bir özelliğidir (belirsiz görünüyor ve olması gerekiyor). Genellikle bir özellik, bir örnek değişkeni döndürür veya ayarlar, ancak birkaçından gelen verileri kullanabilir veya hiç kullanmayabilir. Örneğin:

@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

(Not: Yukarıdaki kod, adın zaten var olduğunu varsaydığı ve en az iki bileşeni olduğu için hatalı. daha az net, bu yüzden sadece buraya işaret ediyorum, böylece kimse masum bir şekilde bu hataları tekrarlamaz.)


4
Mülkleri görüntüleme şeklim, harici nesneler için örnek değişkenlerine erişim sağlama / kısıtlama yoludur. Diğer dillerdeki genel / özel kavram gibi mi?
prototip olarak

"Normalde diğer nesnelerin onlara hiçbir zaman doğrudan erişmesi beklenmez" Bununla ne demek istiyorsun? Ayrıca cevabınız modern hedef-c ile güncellendi mi?
Tatlım

1
@Honey Sanırım kapsülleme kavramına ve en iyi uygulamaları takip etmeye atıfta bulunuyor. Diğer nesneler doğrudan ivar'a erişememeli veya değiştirememelidir. Özellikler aracılığıyla ivar erişimini kontrol ederek, bu çağrıları potansiyel olarak ivar'ı etkilemeden önce durdurabiliriz. Daha fazla bilgi için buraya bakın: en.wikipedia.org/wiki/Encapsulation_(computer_programming)
user3344977

33

Özellik, ek kullanışlı özellikler ve sözdizimi ile belirli bir değer için alıcı / ayarlayıcı uygulamanın kolay bir yoludur. Bir özellik, bir örnek değişkeni tarafından desteklenebilir, ancak alıcı / ayarlayıcıyı biraz daha dinamik bir şey yapmak için de tanımlayabilirsiniz, örneğin, bir üyenin değerini döndürmek yerine sonucu dinamik olarak oluşturan bir dizede bir lowerCase özelliği tanımlayabilirsiniz. değişken.

İşte bir örnek:

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

@interface MyObject {
    NSString *propertyName;

}

// ...

@property (nonatomic, retain) NSString *propertyName;

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

@synthesize propertyName /* = otherVarName */;

@propertyHattı ismi verilen bir özelliğini tanımlayan propertyNameÇeşidi NSString *. Bu, aşağıdaki sözdizimi kullanılarak alınabilir / ayarlanabilir:

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

Atama yaptığınızda veya myObject.propertyNamesizden okuduğunuzda , gerçekten nesnede ayarlayıcı / alıcı yöntemlerini çağırıyorsunuz.

@synthesizeÇizgi değerini depolamak için mülkiyet aynı adla üye değişkeni kullanarak, sizin için bu alıcı / ayarlayıcıları oluşturmak için derleyici söyler (veya otherVarNameyorumlarınızla sözdizimi kullanıyorsanız).

Bununla birlikte @synthesize, kendi alıcıyı tanımlayarak alıcılardan / ayarlayıcılardan birini geçersiz kılabilirsiniz. Bu yöntemler için adlandırma kuralı setPropertyName:ayarlayıcı içindir ve alıcı içindir propertyName(veya getPropertyNamestandart değildir). Diğeri yine sizin için oluşturulacak.

Senin içinde @propertyhat Eğer parçacığı güvenlik ve hafıza yönetimi gibi şeyler otomatik hale getirebilirsiniz özelliği için Pars içinde birkaç özellik tanımlayabilirsiniz. Varsayılan olarak, bir özellik atomiktir, yani derleyici, @synthesizeşzamanlılık sorunlarını önlemek için, alınan get / set çağrılarını uygun kilitlerle sarmalar. Bunu nonatomicdevre dışı bırakmak için özniteliği belirtebilirsiniz (örneğin, çoğu özelliği varsayılan olarak ayarlamak istediğiniz iPhone'da nonatomic).

Herhangi bir @synthesizedayarlayıcı için bellek yönetimini kontrol eden 3 öznitelik değeri vardır . Birincisi , mülkün eski değerlerine ve yeni değerlere retainotomatik olarak gönderilecektir . Bu çok kullanışlıdır.releaseretain

İkincisi, copyaktarılan değerleri saklamak yerine bunların bir kopyasını oluşturacaktır. copyNSString için kullanmak iyi bir uygulamadır, çünkü arayan kişi bir NSMutableString'i geçebilir ve onu altınızdan değiştirebilir. copyyalnızca sizin erişebildiğiniz girdinin yeni bir kopyasını oluşturur.

Üçüncüsü, assigneski veya yeni nesnede tutma / bırakma çağrısı yapmadan düz bir işaretçi ataması yapar.

Son olarak, readonlyözellik için ayarlayıcıyı devre dışı bırakmak için özniteliği de kullanabilirsiniz .


1
Örnek değişkenini ve özelliği (örneğin, propertyName) bildirmenin herhangi bir faydası var mı? Aynı değişken için bir özellik bildirirseniz, arabirim içindeki bildirime gerek yoktur, doğru mu? Kaçırdığım bir şey var sürece bu gerçekten kod satırları üzerinde tasarruf ..
whyoz

6

Arayüz bölümü için özellikler kullanıyorum - diğer nesnelerle ve örnek değişkenleriyle nesne arayüzleri sınıfınızda ihtiyaç duyduğunuz şeylerdir - sizin dışınızda bunları görmeniz ve işlemeniz gerekmiyor.


3

Varsayılan olarak, bir okuma yazma özelliği, derleyici tarafından otomatik olarak yeniden sentezlenecek bir örnek değişkeni tarafından desteklenecektir.

Örnek değişken, var olan ve nesnenin ömrü boyunca değerini tutan bir değişkendir. Örnek değişkenler için kullanılan bellek, nesne ilk yaratıldığında (ayırma yoluyla) tahsis edilir ve nesne serbest bırakıldığında serbest bırakılır.

Siz aksini belirtmediğiniz sürece, sentezlenmiş örnek değişkeni, özellikle aynı ada, ancak bir alt çizgi önekine sahiptir. Örneğin firstName adlı bir özellik için, sentezlenmiş örnek değişkeni _firstName olarak adlandırılır.


2

Önceden insanlar mülkleri genel olarak ve ivars'ı özel kullanım için kullanıyorlardı, ancak birkaç yıldan beri, @implementationbunları özel olarak kullanmak için mülkleri de tanımlayabilirsiniz . Ancak, yazılacak daha az harf olduğundan ve bu makaleye göre daha hızlı çalıştığından, mümkün olduğunda yine de ivars kullanırım . Özellikler "ağır" anlamına geldiği için mantıklıdır: bunlara ya üretilen alıcılardan / ayarlayıcılardan ya da manuel olarak yazılanlardan erişilmesi gerekir.

Ancak Apple'ın son kodlarında ivarlar artık kullanılmıyor. Daha fazla gibi çünkü sanırım objcziyade C/C++, ayrıca birlikte özelliklerini kullanımı daha kolay assign, nullablevb


Tahminimdeki mülklerin Apple kullanımı @implementationSwift ile benzerlikler göstermek istiyor. Yine de, kendi sınıfımın basit bir alanını aramak için (ve özelliğe erişildiğinde olur) sanal bir işlev çağrısını boşa harcamamak için yedek değişkenleri tercih ederim.
Leo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.