成員變量和屬性的區別
一、成員變量
1、概念相關
成員變量:成員變量,成員變量包含基本數據類型的變量和對象類型的變量(實例變量)
實例變量:實例變量是針對類而言,是由類聲明的對象。
2、作用域
變量聲明位置與作用域的關系
- 當成員變量聲明在.m文件中時,則只有該文件可以訪問。
- 當成員變量聲明在.h文件中時,則其訪問權限由修飾詞控制。
四種修飾詞對成員變量作用域的影響具體如下:
- package
整個包中,整個項目中都可以訪問 - private
只有在當前文件中才能訪問 - protected
只有在當前類或者子類文件中訪問 - public
整個項目中都可以訪問
3、驗證
所謂實踐是檢驗真理的唯一標準,這里我們只驗證成員變量聲明在.h文件中的情況,至于聲明在.m中的情況,大家自行探索。
3.1 本類外部訪問:
創建類Teacher,成員變量聲明在Teacher.h中如下:
下面我們來看該類在外部文件對這四個變量的訪問情況,如圖:
對比上圖我們可以得到結論:
1、修飾詞public、pakage修飾的成員變量可以在外部訪問。
3.2 本類內部訪問:
在本類文件訪問截圖:
結合圖2和圖3可以得到結論:
2、修飾詞protected、private修飾的成員變量可以在本類文件中訪問。
3.3 子類外部訪問:
創建ChineseTeacher類繼承自Teacher類,如:
子類在外部文件訪問:
結合圖4和圖5可以得出結論:
3、子類在外部文件中可以訪問父類中用publick和pakage修飾的成員變量。
3.4 子類內部訪問:
在子類.m文件中訪問情況如下:
結合圖6和圖3可以得到:
4、修飾詞protected允許本類以及子類文件中訪問,private修飾的成員變量只有在本類文件中能訪問,子類無法訪問。
apple官方給出的說明如下:
二、屬性
1、屬性聲明都默認做了些什么?
- 聲明屬性時會默認創建格式如:“_屬性名”的成員變量。
- 針對屬性自動生成setter和getter方法存取器。
2、屬性的內存管理
assign :直接進行賦值操作
assign一般用于修飾基本數據類型,也可以修飾對象,但不推薦,assign修飾的對象在釋放之后指針依舊會指向釋放前的內存,在后續操作中可能會導致內存問題崩潰。-
retain:release舊值,再retain新值
retain和strong一樣,都用于修飾oc對象.在set方法中的內部實現實質上是保留新值,釋放舊值,再設置新值。避免新舊值一樣時引起對象被釋放的問題。下面圖1和圖2分別對象ARC和MRC時set方法。
圖1
圖2 strong:ARC中引入的新的修飾詞,具體可參照retain。
-
copy:release舊值,copy新值(拷貝內容)
一般用于修飾String、Dic、Array等需要保護封裝性的對象,尤其是在內容可變時。采用copy進行深拷貝可以有效避免對源內容的篡改。在set方法中實質是先拷貝新值,再釋放舊值,再設置新值。下面圖3和圖4分別對應ARC和MRC時set方法。
圖3
圖4
2.1 @synthesize與@dynamic
現在聲明屬性之后,系統默認會自動生成屬性的setter和getter存取方法。比如:當你在.h文件聲明了屬性:
@property (nonatomic,copy) NSString *name;
那么我們到.m文件中可以發現我們可以使用_name對屬性name進行訪問。其實這個_name是我們聲明屬性之后系統默認創建的。系統默認做了這樣幾件事:
- 1.按照對應格式:
@property x ==> _x
生成與屬性一一對應的成員變量,并且將屬性與該成員變量綁定。
- 2.自動合成操作屬性setter和getter方法,實表面我們操作的是屬性,實際上操作與屬性綁定的成員變量。
以上兩點在屬性聲明之后系統的初始化操作。其實我們可以借助關鍵字synthesize和dynamic對上面兩點進行控制。我們先看看@synthesize和@dynamic的作用:
@synthesize
1、讓編譯器自動生成屬性的存取方法,并將存取方法作用于系統根據屬性名創建的(_+屬性名)變量。
2、當我們自定義存取方法時可以覆蓋系統自動生成的存取方法。(注意當我們重寫set和get方法時系統不會自動創建1中提到的變量,這時需要我們自己聲明實例變量)@dynamic
告訴編譯器不自動生成存取方法,由開發者自行實現存取方法。