繼承
方法重寫
在子類中實現與父類中同名的方法,稱之為方法重寫;
重寫以后當給子類發送這個消息的時候,執行的是在子類中重寫的那個方法,而不是父類中的方法。
如果想在子類中調用被子類重寫的父類的方法,可以通過super關鍵字
使用場景:當從父類繼承的某個方法不適合子類,可以在子類中重寫父類的這個方法。
繼承中方法調用順序
1、在自己類中找
2、如果沒有,去父類中找
3、如果父類中沒有,就去父類的父類中
4、如果父類的父類也沒有,就還往上找,直到找到基類(NSObject)
5、如果NSObject都沒有就報錯了
- 如果找到了就執行這個方法,就不再往后查找了
OC中的繼承關系
B類繼承A類,那么B類將擁有A類的所有屬性和方法,此時我們說A類是B類的父類,B類是A類的子類
C類繼承B類,那么C類將擁有B類中的所有屬性和方法,包括B類從A類中繼承過來的屬性和方法,此時我們說B類是C類的父類,C類是B類的子類
注意:
基類的私有屬性能被繼承,不能在子類中訪問。
OC中的繼承是單繼承:也就是說一個類只能一個父類,不能繼承多個父類
子類與父類的關系也稱為isA(是一個)關系,我們說 子類isA父類,也就是子類是一個父類,比如狗類繼承動物類,那么我們說狗isA動物,也就是狗是一個動物。在如汽車繼承交通工具,那么們說汽車isA交工工具,也就是汽車是一個交通工具
繼承的合理性:引用《大話西游》里的一句話來描述繼承的。“人是人他媽生的,妖是妖他媽生的!”
繼承的注意事項
子類不能定義和父類同名的成員變量,私有成員變量也不可以;因為子類繼承父類,子類將會擁有父類的所有成員變量,若在子類中定義父類同名成員變量 屬于重復定義。
OC類支持單一繼承,不支持多繼承;也就是說一個類只能有一個直接父類
多態基本概念
什么是多態
多態就是某一類事物的多種形態
程序中的多態:父類指針指向子類對象
多態的條件
有繼承關系
子類重寫父類方法
父類指針指向子類對象
表現:當父類指針指向不同的對象的時候,通過父類指針調用被重寫的方法的時候,會執行該指針所指向的那個對象的方法
多態的主要好處就是簡化了編程接口.它允許在類和類之間重用一些習慣性的命名,而不用為每一個新加的函數命名一個新名字.這樣,編程接口就是一些抽象的行為的集合,從而和實現接口的類的區分開來.
多態也使得代碼可以分散在不同的對象中而不用 試圖在一個函數中考慮到所有可能的對象這樣使得您的代碼擴展性和復用性更好一些.當一個新的情景出現時,您無須對現有的代碼進行改動,而只需要增加一個新的類和新的同名方法.
私有變量和私有方法
私有變量
- 實例變量(成員變量)既可以在@interface中定義, 也可以在@implementation中定義
寫在@implementation中的成員變量, 默認就是私有的成員變量, 并且和利用@private修飾的不太一樣, 在@implementation中定義的成員變量在其它類中無法查看, 也無法訪問
在@implementation中定義的私有變量只能在本類中訪問,在其他類中無法查看,也無法訪問
- 無論使用什么成員變量修飾符修飾成員變量,我們都可以在其他類中看到這個變量,只不過有的成員變量修飾符修飾的變量我們不能操作而已.
私有方法
如果只有方法的實現,沒有方法的聲明,那么該方法就是私有方法
在OC中沒有真正的私有方法,因為OC是消息機制
@property編譯器指令
什么是編譯器指令? 編譯器指令就是用來告訴編譯器要做什么
@property會讓編譯器做什么呢?
@property 用在聲明文件中告訴編譯器聲明成員變量的的訪問器(getter/setter)方法
這樣的好處是:免去我們手工書寫getter和setter方法繁瑣的代碼
@property編寫步驟
1.在@inteface和@end之間寫上@property
2.在@property后面寫上需要生成getter/setter方法聲明的屬性名稱, 注意因為getter/setter方法名稱中得屬性不需要_, 所以@property后的屬性也不需要_.并且@property和屬性名稱之間要用空格隔開
3.在@property和屬性名字之間告訴需要生成的屬性的數據類型, 注意兩邊都需要加上空格隔開
synthesize基本使用
什么是@synthesianze
@synthesize是編譯器的指令
什么是編譯器的指令 ?
- 編譯器指令就是用來告訴編譯器要做什么!
- @synthesize會讓編譯器做什么呢?
@synthesize 用在實現文件中告訴編譯器實現成員變量的的訪問器(getter/setter)方法
這樣的好處是:免去我們手工書寫getterr和setter方法繁瑣的代碼
@synthesize基本使用
- 在@implementation中, 用來自動生成setter和getter的實現
用@synthesize age = _age;就可以代替
- (int)age{
return _age;
}
- (void)setAge:(int)age{
_age = age;
}
- @synthesize編寫步驟
1.在@implementation和@end之間寫上@synthesize
2.在@synthesize后面寫上和@property中一樣的屬性名稱, 這樣@synthesize就會將@property生成的什么拷貝到@implementation中
3.由于getter/setter方法實現是要將傳入的形參 給屬性和獲取屬性的值,所以在@synthesize的屬性后面寫上要將傳入的值賦值給誰和要返回哪個屬性的值, 并用等號連接
@synthesize注意點
- @synthesize age = _age;
setter和getter實現中會訪問成員變量_age
如果成員變量_age不存在,就會自動生成一個@private的成員變量_age
- @synthesize age;
setter和getter實現中會訪問@synthesize后同名成員變量age
如果成員變量age不存在,就會自動生成一個@private的成員變量age
- 多個屬性可以通過一行@synthesize搞定,多個屬性之間用逗號連接
@synthesize age = _age, number = _number, name = _name;
@property增強
- 自從Xcode 4.x后,@property可以同時生成setter和getter的聲明和實現
@interface Person : NSObject
{
int _age;
}
@property int age;
@end
@property增強注意點
- 默認情況下,setter和getter方法中的實現,會去訪問下劃線 _ 開頭的成員變量。
@interface Person : NSObject
{
@public
int _age;
int age;
}
@property int age;
@end
int main(int argc, const char * argv[]) {
Person *p = [Person new];
[p setAge:30];
NSLog(@"age = %i, _age = %i", p->age, p->_age);
return 0;
}
如果沒有會自動生成一個_開頭的成員變量,自動生成的成員變量是私有變量, 聲明在.m中,在其它文件中無法查看,但當可以在本類中查看
@property只會生成最簡單的getter/setter方法,而不會進行數據判斷
Person *p = [Person new];
[p setAge:-10];
NSLog(@"age = %i", [p age]);
- 如果需要對數據進行判斷需要我們之間重寫getter/setter方法
若手動實現了setter方法,編譯器就只會自動生成getter方法
若手動實現了getter方法,編譯器就只會自動生成setter方法
若同時手動實現了setter和getter方法,編譯器就不會自動生成不存在的成員變量
@property修飾符
- 【掌握】@property修飾符
@property修飾符
- 修飾是否生成getter方法的
readonly 只生成getter方法,不生成setter方法
readwrite 既生成getter 又生成setter方法(默認)
@property (readonly) int age;
- 指定所生成的方法的方法名稱
getter=你定制的getter方法名稱
setter=你定義的setter方法名稱(注意setter方法必須要有 :)
@property (getter=isMarried) BOOL married;
說明,通常BOOL類型的屬性的getter方法要以is開頭
new方法實現原理
完整的創建一個可用的對象:Person *p=[Person new];
new方法的內部會分別調用兩個方法來完成3件事情:
(1)使用alloc方法來分配存儲空間(返回分配的對象);
(2)使用init方法來對對象進行初始化。
(3)返回對象的首地址
- 可以把new方法拆開如下:
(1)調用類方法+alloc分配存儲空間,返回未經初始化的對象
Person *p1=[person alloc];
(2)調用對象方法-init進行初始化,返回對象本身
Person *p2=[p1 init];
- (3)以上兩個過程整合為一句:
Person *p=[[Person alloc] init];
- 說明:
alloc 與 init合起來稱為構造方法,表示構造一個對象
alloc 方法為對象分配存儲空間,并將所分配這一塊區域全部清0.
The isa instance variable of the new instance is initialized to a data structure that describes the class; memory for all other instance variables is set to 0.
- init方法是初始化方法(構造方法),用來對象成員變量進行初始化,默認實現是一個空方法。
An object isn’t ready to be used until it has been initialized. The init method defined in the NSObject class does no initialization; it simply returns self.
- 所以下面兩句的作用是等價的
Person *p1 = [Person new];
Person *p = [[Person alloc] init];
- iOS 程序通常使用[[類名 alloc] init] 的方式創建對象,因為這個可以與其他initWithXX:...的初始化方法,統一來。代碼更加統一