版本
Xcode 8.3.2
一、Class(類)
前面已經(jīng)接觸過NSString、NSArray、NSMutableDictionary等等系統(tǒng)類,今天我們來看看如何創(chuàng)建自己的類。要創(chuàng)建類,首先要先認識類。
在OC中,類包含兩個部分:聲明和實現(xiàn)。
聲明以@interface開頭,以@end結(jié)尾。中間聲明屬性和方法。
@interface Person : NSObject
/*
聲明屬性(成員變量)、方法
*/
@end
實現(xiàn)以@implementation開頭,以@end結(jié)尾。中間實現(xiàn)方法。
@implementation Person
/*
方法的實現(xiàn)
*/
@end
1、繼承
OC中幾乎所有的類都是繼承而來,且最終都繼承于基類NSObject。
繼承的類叫子類,被繼承的類叫父類,子類會繼承父類的所有屬性和方法。
@interface Person : NSObject
意思是Person繼承于NSObject,即Person為子類,NSObject為父類。
@interface Man : Person
同樣我們也可以創(chuàng)建一個類Man繼承于Person,那么,子類Man就擁有了父類Person的所有屬性和方法。
2、屬性(成員變量)
OC中所有方法均為公有方法,所以O(shè)C要實現(xiàn)函數(shù)的私有化(在類外部不能直接調(diào)用),是通過隱藏函數(shù)名(只寫實現(xiàn)不寫聲明)。
方法在父類實現(xiàn)不聲明,在子類聲明不實現(xiàn),子類也可調(diào)用該父類方法。
@interface Person : NSObject {
@public //在類的內(nèi)部或外部(對象或子類)都可以直接訪問,直接訪問時格式: 對象->變量名
NSString *_name;
@protected //受保護類型(默認),在子類中也可直接訪問
NSInteger _age;
@private //私有類型,在類外部不能直接訪問,在子類中有繼承但不能直接訪問,可通過self.方法 調(diào)用setter等間接訪問
NSInteger _weight;
}
@end
命名規(guī)范:在{}中聲明成員變量要加下劃線_
3、類方法和對象方法
類方法以+開頭,對象方法以-開頭。如:
+ (void)eat;
- (void)workOvertime;
假如我們對類Person進行實例化,得到一個對象XiaoKang,那么,Person只能調(diào)用eat方法;而XiaoKang只能調(diào)用workOvertime方法。
Person *XiaoKang = [[Person alloc] init];
[Person eat];
[XiaoKang workOvertime];
即類方法只能由類調(diào)用,對象方法只能由對象調(diào)用。
二、@property屬性
1、點語法
假如我們設(shè)置了setter和getter方法:
// .h中聲明
@interface Person : NSObject {
NSInteger _age;
}
- (void)setAge:(NSInteger)newAge;
- (NSInteger)age;
@end
// .m中實現(xiàn)
@implementation Person
- (void)setAge:(NSInteger)newAge {
_age = newAge;
}
- (NSInteger)age {
return _age;
}
@end
那么就可以使用點語法:
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
Person *XiaoKang = [[Person alloc] init];
// 經(jīng)典方法
[XiaoKang setAge:18];
NSLog(@"經(jīng)典方法: %ld",[XiaoKang age]);
// 點語法
XiaoKang.age = 25;
NSLog(@"點語法: %ld",XiaoKang.age);
return 0;
}
結(jié)果:
如果要通過點語法調(diào)用setter或getter函數(shù),需滿足:
setter:-(void)set+(首先成員變量去掉””,并且首字母大寫):(成員變量的指針類型)
getter:-(成員變量的指針類型)+(去掉””之后的成員變量的變量名)
既然這種寫法都是固定好的,那么有沒有更好的方法,使用起來更加方便呢?其實,Apple已經(jīng)做了這些事情。我們可以:
.h文件中
// 用下面這一行
@property NSInteger age;
// 來代替setter和getter方法的聲明
//- (void)setAge:(NSInteger)newAge;
//- (NSInteger)age;
.m文件中
// 用下面這一行
@synthesize age = _age;
// 來代替setter和getter方法的實現(xiàn)
//- (void)setAge:(NSInteger)newAge {
//
// _age = newAge;
//}
//
//
//- (NSInteger)age {
//
// return _age;
//}
效果也是一樣的。
2、property屬性(增強)
//查找是否缺失setter或getter,如果沒有,則補齊setter和getter
//生成的變量自動帶"_",屬性聲明的變量為私有類型
@property NSInteger age;
//可讀可寫,可生成setter和getter,默認屬性,互相不沖突的屬性可寫多個
@property (readwrite) NSInteger age;
//只讀,只生成getter
@property (readonly) NSInteger age;
//setter:給setter起別名
//getter:給getter起別名
@property (setter = setAge:,getter = getAge)NSInteger age;
@property增強:Xcode4.4之后,使用@property可以生成setter和getter方法的聲明和實現(xiàn),同時還會生成一個私有的成員變量(_屬性名稱)。也就是說,不必要再在{}里面聲明成員變量,也沒有必要寫@synthesize。
注意:
- 如果我們自定義(重寫)setter方法,@property就不會生成它的setter方法,但是仍然會幫我們生成getter方法和私有的成員變量;
- 如果我們自定義(重寫)getter方法,@property就不會生成它的getter方法,但是仍然會幫我們生成setter方法和私有的成員變量;
- 如果我們同時自定義(重寫)setter和getter方法,@property就不會生成它的setter和getter方法,也不會幫我們生成setter、getter方法和私有的成員變量。
3、屬性修飾符
//MRC下 屬性修飾符下的強弱引用
//只要是OC對象,都要使用強引用,C語言基本類型,可以使用弱引用
//assign屬性修飾符下默認生成的setter為弱引用(_age = age)
@property (nonatomic,assign)NSInteger age;
//retain屬性修飾符下默認生成的setter為強引用,可變字符串也用retain
@property (nonatomic,retain)NSMutableArray *arr;
//copy屬性修飾符下默認生成的setter為強引用,一般用于NSString*
@property (nonatomic,copy)NSString *name;
//ARC下 新增的賦值操作(兼容MRC下的修飾符)
//strong:強引用,默認,修飾對象指針,會自動retain或release,ARC環(huán)境下蘋果推薦使用
//只要一個對象還有強引用指針指向它,它就永遠不能被釋放掉
@property (nonatomic,strong) NSMutableArray *arr1;
@property (nonatomic,copy) NSString* name1;
@property (nonatomic,assign) NSInteger age1;
//weak:弱引用,修飾對象指針,不修飾C的基本類型,指向的對象消失時,自動變成nil
//@property (nonatomic,weak) NSMutableArray *arr2;
//unsafe_unretained:相當于weak,當指向的對象消失時,不會自動變成nil
如果還不太理解,參照如下:
1、使用assign:
對基礎(chǔ)數(shù)據(jù)類型 (NSInteger,CGFloat,,bool)和C數(shù)據(jù)類型(int, float, double, char, 等等);
2、使用copy:
對NSString;
3、使用retain:
對其他NSObject和其子類。