天天看點

程式設計筆記(objective-c :關于屬性)關于屬性

轉載請标明出處:blog.csdn.net/zhangxingping

關于屬性

        在C++中,通常需要編寫Getter和Setter方法來擷取或者是設定執行個體變量的值。這兩種方法需要在程式中顯示的完成。這種方式在Objective-C中也是适用的。但是Objective-C提供了一種更為便捷的方式來完成這種功能。它就是屬性。和C++中的顯示的Getter和Setter方法相比,屬性機制使得Getter函數和Setter來的更容易和更簡化。

Objectivc-C中的屬性是通過關鍵字@property來聲明的。

例如,有類如下:

Student.h檔案:

#import <Foundation/Foundation.h>
 
 
@interface Student : NSObject
{
@private
    NSString * name;  //學生的姓名
    float math;       //數學科目的成績
    float english;    //英語科目的成績 
   
}
 
 
-(id)initWithName:(NSString*)aName math:(float)scoreMath english:(float)scoreEnglish;
 
-(NSString *)getName;
-(float)getMath;
-(float)getEnglish;
 
@end
           

Student.m檔案:

#import "Student.h"
 
@implementation Student
 
- (id)init
{
    self = [super init];
    if (self)
    {
        name = nil;
        math = 0;
        english = 0;
    }
   
    return self;
}
 
-(id)initWithName:(NSString*)aName math:(float)scoreMath english:(float)scoreEnglish
{
    self = [super init];
    if (self)
    {
        name = aName;
        math = scoreMath;
        english = scoreEnglish;
    }
   
    return self;
}
 
-(NSString *)getName
{
    return name;
}
 
-(float)getMath
{
    return math;
}
 
-(float)getEnglish
{
    return english;
}
 
- (void)dealloc
{
    [super dealloc];
}
 
@end
           

main.m檔案如下:

 #import <Foundation/Foundation.h>

#import "Student.h"
 
int main (int argc, const char * argv[])
{
 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   
    Student * p = [[Student alloc] initWithName:@"Mark" math:80.0f english:100.00f];
   
    NSLog(@"Name:%@",[p getName]);
    NSLog(@"Math:%f",[p getMath]);
    NSLog(@"Math:%f",[p getEnglish]);   
   
    [p release];
 
    [pool drain];
    return 0;
}
           

上面程式的輸出結果如下:

Name:Mark

Math:80.000000

Math:100.000000

上面的程式是通過C++中的方式來編寫Getter方法來擷取私有的執行個體變量的值。這些個Getter方法實作雖然簡單,但是必需有程式員顯示書寫來完成。應用屬性機制後,程式如下:

Student.h檔案:

#import <Foundation/Foundation.h>
 
@interface Student : NSObject
{
@private
    NSString * name;  //學生的姓名
    float math;       //數學科目的成績
    float english;    //英語科目的成績 
   
}
 
@property NSString * name;
@property float math;
@property float english;
 
 
 
-(id)initWithName:(NSString*)aName math:(float)scoreMath english:(float)scoreEnglish;
 
//-(NSString *)getName;
//-(float)getMath;
//-(float)getEnglish;
 
@end
           

Student.m檔案:

#import "Student.h"
@implementation Student
 
@synthesize name;
@synthesize math;
@synthesize english;
 
- (id)init
{
    self = [super init];
    if (self)
    {
        name = nil;
        math = 0;
        english = 0;
    }
   
    return self;
}
 
-(id)initWithName:(NSString*)aName math:(float)scoreMath english:(float)scoreEnglish
{
    self = [super init];
    if (self)
    {
        name = aName;
        math = scoreMath;
        english = scoreEnglish;
    }
   
    return self;
}
 
//-(NSString *)getName
//{
//    return name;
//}
//
//-(float)getMath
//{
//    return math;
//}
//
//-(float)getEnglish
//{
//    return english;
//}
//
//- (void)dealloc
//{
//    [super dealloc];
//}
 
@end
           

main.m檔案如下: 

#import <Foundation/Foundation.h>
#import "Student.h"
 
int main (int argc, const char * argv[])
{
 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   
    Student * p = [[Student alloc] initWithName:@"Mark" math:80.0f english:100.00f];
   
//  NSLog(@"Name:%@",[p getName]);
//  NSLog(@"Math:%f",[p getMath]);
//  NSLog(@"Math:%f",[p getEnglish]);   
    NSLog(@"Name:%@",p.name);
    NSLog(@"Math:%f",p.math);
    NSLog(@"Math:%f",p.english);  
   
    [p release];
 
    [pool drain];
    return 0;
}
           

程式的輸出如下:

Name:Mark

Math:80.000000

Math:100.000000

可見屬性機制使得程式更加簡潔明了。

上面程式中引入了新的關鍵字@synthesize,這個關鍵字告訴編譯器自動為其後面的屬性生成Getter()和Setter()方法。需要注意的一點是雖然在描述上适用的是“自動生成Getter()和Setter()方法”,但是實際上我們并看不到生成的對應代碼。需要明确的是編譯器自動生成的Getter方法:name(),math(),english()以及Sette方法:setName(), setMath(), setEnglish()的調用完全和普通的方法是一樣的。例如我們可以修改上面的main()函數如下:

#import <Foundation/Foundation.h>
#import "Student.h"
 
int main (int argc, const char * argv[])
{
 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   
    Student * p = [[Student alloc] initWithName:@"Mark" math:80.0f english:100.00f];
   
//  NSLog(@"Name:%@",[p getName]);
//  NSLog(@"Math:%f",[p getMath]);
//  NSLog(@"Math:%f",[p getEnglish]);
   
   
//    NSLog(@"Name:%@",p.name);
//    NSLog(@"Math:%f",p.math);
//    NSLog(@"Math:%f",p.english);  
   
    [p setName:@"Tony"];
    [p setMath:99.0f];
    [p setEnglish:89.98f];   
 
    NSLog(@"Name:%@",[p name]);
    NSLog(@"Math:%f",[p math]);
    NSLog(@"Math:%f",[p english]);  
 
 
   
    [p release];
 
    [pool drain];
    return 0;
}
           

程式輸出為:

Name:Tony

Math:99.000000

Math:89.980003

        上面的程式在Xcode中編譯後,會在@property NSString * name;代碼的所在行頭看到一個黃色的歎号,這表明編譯器在該行代碼處給出了編譯警告。單擊該黃色歎号可以看到給出的警告資訊:“No 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed”和“Default property attribute 'assign' not appropriate for non-gc object”。警告資訊的意思是:“沒有明确指出應該是assign還是retain或者是copy,卻省的是assign”和“預設得屬性設定assign不适合非gc對象 ”,那麼這兩個警告資訊的含義具體是什麼呢?assign,retian,copy又分别代表什麼含義呢?什麼是gc對象呢?什麼是非gc對象呢?這些問題見後文描述。

繼續閱讀