OC-@property、self及類的本質

来源:http://www.cnblogs.com/wang-biao/archive/2016/07/12/5663197.html
-Advertisement-
Play Games

讓代碼書寫更加簡便 【寫在開頭】 『在面向對象的編程中,封裝是其一個重要的特性。封裝將一個可供外部使用的介面暴露出來,隱藏了複雜的代碼邏輯實現。 外部就可以通過設置器setter和訪問器getter來對對象的屬性進行設置和訪問,而不是直接訪問對象的屬性-> --1-- 設置器和訪問器 1.1 set ...


讓代碼書寫更加簡便

--1-- 設置器和訪問器
1.1 setter
1.2 getter
--2-- 類的本質
2.1 類類型的對象
2.2 類的本質
2.3 如何獲取類對象
2.4 類對象的使用
2.5 類對象的存儲
--3-- SEL類型
3.1 SEL
--4-- @property關鍵字
4.1 基本概念
4.2 @property用法
4.3 @property使用註意事項
--5-- @synthesize關鍵字
5.1 @synthesize用法
5.2 @synthesize使用註意
5.3 @synthesize指定實例變數賦值
--6-- self關鍵字
6.1 介紹
6.2 在對象方法中使用self
6.3 用在類方法中使用self
-------------------------------------

 

 

【寫在開頭】

『在面向對象的編程中,封裝是其一個重要的特性。封裝將一個可供外部使用的介面暴露出來,隱藏了複雜的代碼邏輯實現。

不可被外部任意存儲是面向對象設計的本質,降低了數據被無用的可能性。

外部就可以通過設置器setter和訪問器getter來對對象的屬性進行設置和訪問,而不是直接訪問對象的屬性(->)

在開發過程中,考慮到安全性要求,一般不再成員變數名前面使用@public@protected等關鍵字修飾,而是使用Set方法來為對象提供成員變數的值,在set方法的內部也可以對一些不合理的賦值進行篩選過濾。

 

 

--1-- 設置器和訪問器

1.1 setter

setter方法(設置器):在set方法的內部可以對一些不合理的數據過濾篩選。set方法作用:為提供一個設置成員變數值的方法。

命名規範:

1)方法名必須以set開頭

2)set後面跟上成員變數的名稱,首字母大寫

3)返回值一定是void

4)一定要接受一個參數,而且參數類型需要和成員變數的類型一致

5)形參名不能和變數名一樣(成員變數名以_線開頭,蘋果官方推薦成員變數名前加_以示區分)

好處:

  1)不讓數據暴露在外,保證了數據的安全性

  2)對設置的數據進行過濾

{
    //成員屬性
    NSString *_name;
    int _age;
}

setter

//setter
- (void)setName:(NSString *)name;
- (void)setAage:(int)age;

 

1.2 getter

作用:為調用者返回對象內部的成員變數

命名規範:

1)一定有返回值,返回值的類型和成員變數的類型一致

2)方法名和去掉下劃線的成員變數名一樣(此處與Java等語言不一樣)

3)不需要接收任何參數 

//getter
- (NSString *)name;
- (int)age;

 

 

--2-- 類的本質

2.1 類類型的對象

類的本質其實也是對象,只不過是class類型的對象,也叫做類對象

 

2.2 類對象

類對象

* 類對象在程式運行時一直存在

* 類對象是一種數據結構,存儲類的基本信息:類大小,類名,類的版本以及消息與函數的映射表等

* 類對象所保存的信息是在程式編譯時確定,在第一次使用該類的時候被載入到記憶體中

* 類對象代表類,class代表類對象,類方法屬於類對象

* 如果消息的接收者是類名,則類名代表類對象

* 運行時,所有類的實例都由類對象生成,類對象會把實例的isa的值修改成自己的地址,每個實例的isa都指向該實例的類對象

* 從類對象里可以知道父類的信息、可以響應的方法等

* 類對象只能使用類方法,不能使用實例方法

 

2.3 如何獲取類對象

1)通過實例對象獲取

    Person *person = [[Person alloc] init]; //創建對象
        
    //通過實例對象獲取類對象Dog
    Class c1 = [person class]; //Class類型的是一個結構體指針
    Class c2 = [person class];
        
    NSLog(@"c1->%p", c1); //0x1000011d8
    NSLog(@"c2->%p", c2); //0x1000011d8

 

2)通過類名獲取(類名其實就是類對象)

    //通過類名獲取類對象
    Class c3 = [Person class];
    
    NSLog(@"c3->%p", c3); //0x1000011d8

發現通過類名和實例獲取對象,所獲得的對象是同一個

實際上,都是獲得了類對象Person class

 

2.4 類對象的使用

1)用類對象創建對象

兩個測試方法:

//對象方法
- (void)test;

//類方法
+ (void)test;

使用

    //用類對象來創建對象
    Person *person2 = [[c1 alloc] init];
    [person2 test]; //調用對象方法的test -test

 

 2)用類對象來調用類方法

    //用類對象來調用類方法
    [c1 test]; //調用類方法 +test

 

2.5 類對象的存儲

isa指針

  • 每一個對象都包含一個isa指針.這個指針指向當前對象所屬的類。
  • [p eat];表示給p所指向的對象發送一條eat消息,調用對象的eat方法,此時對象會順著內部的isa指針找到存 儲於類中的方法,執行。
  • isa是對象中的隱藏指針,指向創建這個對象的類。
  • 通過isa指針我們可以在運行的時候知道當前對象是屬於那個Class(類)的。

 

 

--3-- SEL類型

3.1 SEL

SEL:全稱selector表示方法的存儲位置

方法調用的原理:其實每個類載入到記憶體中對象的方法都會封裝成一系列的SEL列表,SEL會保存著這個方法的信息(當然包括方法的記憶體地址),當要調用該方法的時候,對象會通過isa指針找到記憶體中對應的方法的記憶體地址然後再調用該方法,在找到該方法之後該類對象會把該SEL放入緩存中,以便第二次尋找的時候提高效率

 

Person *p = [[Person alloc] init];

[p test]; 

尋找方法的過程

1)首先把test這個方法名包裝成SEL類型的數據

2)根據SEL數據找到對應的方法地址

3)根據方法地址調用相應的方法

4註意:在這個操作過程中有緩存,第一次找的時候是一個一個的找,非常耗性能,之後再用到的時候就直接使用了

 

 

--4-- @property關鍵字

4.1 基本概念

@property是編譯器的指令。(編譯器指令是由編譯器完成的)

好處是免去我們手工書寫成員屬性getter和setter方法繁瑣的代碼。

 

4.2 @property用法

格式:

  @property  類型名  方法名

 如:

  @property  int  age;

相當於完成了age屬性的set和get方法的聲明和實現

 - (void)setAge:(int)age;

 - (void)age;

註意:

1、在Xcode4.4之前,用於幫我們實現get/set方法的聲明

2、在Xcode4.4之後,有增強功能,連實現也自動完成了

Person.h->

/*
  省略了方法的聲明
  相當於是替換了下麵的這兩句聲明
  - (void)setAge:(int)age;
  - (int)age;
 
 同時,還自動生成了對應的成員屬性 _age,但是這個屬性是私有的,外部只能通過setter/getter訪問
  */
@property int age;

Person類中沒有自定義 _age屬性,但是@property自動生成了該屬性:

@implementation Person
//對象方法
- (void)test{
    NSLog(@"-TEST");
    self->_age = 3; //在這裡可以看到,@property生成了一個_age屬性
}

//類方法
+ (void)test{
    NSLog(@"+TEST");
}
@end

調用:

Person *person = [[Person alloc] init]; //創建對象
        
//此處 _age屬性由@property生成
person.age = 3; //設置成員屬性
NSLog(@"person.age->%d", person.age); //3

 

4.3 @property使用註意事項

在老式的代碼中

@property只能寫在@interface ...@end之間

@property用來自動生成成員變數get/set方法的聲明(Xcode4.4之前)

告訴@property要生成的get/set方法聲明的成員變數類型是聲明

告訴@property要生成的get/set方法是哪個屬性的,屬性名去掉下劃線

 

 

--5-- @synthesize關鍵字

5.1 @synthesize用法

@synthesize age;

寫在.m文件中,表示對生成.h中變數age的get和set方法的實現

格式:

  @synthesize  方法名

 註意:

如果使用@synthesize則變數名要先在.h文件中聲明

.h

@property int age;

.m

@synthesize age;

展開形式如下:

@synthesize age; 
//展開
- (void)setAge:(int)age{
    self->age = age; //註意這裡不是對Person原來的成員變數_age賦值,而是生成了一個變數age,然後對其進行賦值
//(如果這裡寫self,那麼這個變數age也就相當於是個成員變數了)
 
    //所以使用@synthesize時,下麵只列印了age和name的值,沒有對_age和_name進行操作
    //NSLog(@"age = %d, name = %@", age, name);
    //NSLog(@"_age = %d, _name = %@", _age, _name);
 }

 

5.2 @synthesize使用註意

Xcode4.4之前@property和@synthesize搭配使用,用於簡化set和get方法的定義和實現

 

5.3 @synthesize指定實例變數賦值

聲明

@property  int  a;   

實現

@sythesize  a  =  _b;   //表示用a的get和set方法,修改屬性b的值

相當於下麵的代碼:

   - (void) setA:(int)a{

  _b = a;

  }

   - (int)a{

  reurn _b;

  }

@interface Person : NSObject

@property NSString *name;
//如果兩個實例變數的類型一致,如:age和weight,@property可以用逗號隔開變數,在一行上定義
@property int age, weight; 

//測試方法
- (void)test;
@end


@implementation Person

//用age的getter和setter方法,修改屬性_age的值
@synthesize age = _age, name = _name, weight = _weight;
@end

 

 

--6-- self關鍵字

6.1 介紹

OC語言中的self,就相當於C++、Java中的this指針。

學會使用self,首先要搞清楚屬性這一概念。

以及理解getter(訪問器)和setter(設置器)方法,它到底有什麼用?

設置器與訪問器,提供外界操作 類內部屬性的一個通道。

 

假如沒有這個方法,外界怎麼操作類的內部屬性。

假如不提供這兩個方法,那麼這個屬性的值,就不能為外界所改變。

因為類的屬性,預設是@protect(受保護類型)。

 

self的應用場景

1)用在類方法中

2)用在對象方法中

3)訪問成員變數

4)self在OC的記憶體管理特殊使用

 

6.2 在對象方法中使用self

//學生學習對象方法
- (void)study{
    
    //此時self指代學生對象
    NSLog(@"- self->%p", self); //0x1002001b0
}

 

6.3 用在類方法中使用self

//學生信息類方法
+ (void)info{
    
    //此時self指代學生類
    NSLog(@"+ self->%p", self); //0x1000013d0
}

查看:

    @autoreleasepool {
        
        Student *stu = [[Student alloc] init];
        
        //學生對象地址
        NSLog(@"stu->%p", stu); //0x1002001b0
        
        //學生類地址
        NSLog(@"Student-%p", [Student class]); //0x1000013d0
        
        //發送study和info消息
        [Student info]; //0x1000013d0
        [stu study]; //0x1002001b0
    }

輸出-->

 

綜上總結:

self要指代誰?具體是要看self寫在哪個方法中,

如果self寫在對象方法中,則指代的就是當前方法的對象([類 new])

如果self寫在類方法中,那麼它指代的就是當前的類對象(類 class)

註意這裡類對象和對象是兩個概念

 

 

【寫在結尾:】

『想起一首席慕容的詩:

一棵開花的樹

如何讓你遇見我
在我最美麗的時刻
	
為這
我已在佛前求了五百年
求佛讓我們結一段塵緣
佛於是把我化做一棵樹
長在你必經的路旁
	
陽光下
慎重地開滿了花
朵朵都是我前世的盼望
	
當你走近
請你細聽
那顫抖的葉
是我等待的熱情
	
而當你終於無視地走過
在你身後落了一地的
朋友啊
那不是花瓣
那是我凋零的心』

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 先來跟大家說說什麼是JQ , JQ是java script Jquery版本庫的縮寫. jQuery是一套跨瀏覽器的JavaScript庫,簡化HTML與JavaScript之間的操作。由John Resig在2006年1月的BarCamp NYC上發佈第一個版本。目前是由 Dave Methvin ...
  • 雖然cookie , localstorge , sessionstorge三者都有存儲的功能,但是還是有區別, git上地址:https://github.com/lily1010/cookie-storge 我個人的總結如下: 一 Cookie問題 ①Cookie是什麼 Cookie 是一小段文 ...
  • 常用的幾種對象創建模式 使用new關鍵字創建 最基礎的對象創建方式,無非就是和其他多數語言一樣說的一樣:沒對象,你new一個呀! 使用字面量創建 這樣似乎妥妥的了,但是宅寂的geek們豈能喜歡如此複雜和low土的定義變數的方式,作為一門腳本語言那應該有和其他兄弟們一樣的範兒,於是出現了對象字面量的定 ...
  • undefined symbols for architecture x86_64 錯誤如下 因為提示文件非第三方文件,最初嘗試使用以下方式處理 iOS :undefined symbols for architecture x86_64錯誤解決方案 在搜索時發現相關的文件不存在,在xcode搜索卻 ...
  • 1.獲得當前運行的activity棧,同時也可以用此命令查看到具體某一頁面的activity名字 adb shell dumpsys activity|grep Run 2.獲得手機安裝的所有應用包名 adb shell pm list packages 3.獲得已安裝的應用的apk,導出到pc a ...
  • The IntentService class provides a straightforward structure for running an operation on a single background thread. This allows it to handle long run ...
  • 如果想自學Android,以下的文章可以作為參考: 如何自學Android(Gityuan) 那兩年煉就的Android內功修養(老羅的Android之旅) ...
  • 通知的機制是一對多,而block和delegate的機制是一對一,通知是好用,但小伙伴麽要記得通知比較耗性能哦~~~ 誰要發送消息,誰就發出通知,誰要接受消息,誰就銷毀通知. 下麵直接來看代碼: //發出通知 [[NSNotificationCenter defaultCenter] postNot ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...