Object-C基礎-02-第一個OC的類

1、語法簡介

1.類

在Java中,咱們用1個.java文件就能夠描述清楚一個類;在OC中,通常用2個文件來描述一個類:html

1> .h:類的聲明文件,用於聲明成員變量、方法。類的聲明使用關鍵字@interface @end java

注意:.h中的方法只是作一個聲明,並不對方法進行實現。也就是說,只是說明一下方法名、方法的返回值類型、方法接收的參數類型而已,並不會編寫方法內部的代碼。ios

2> .m:類的實現文件,用於實現.h中聲明的方法。類的實現使用關鍵字@implementation@end 函數

2.方法

1> 方法的聲明和實現,都必須以 + 或者 - 開頭spa

  • + 表示方法(靜態方法).net

  • - 表示對象方法(動態方法)指針

2> 在.h中聲明的全部方法做用域都是public類型,不能更改code

3.成員變量

成員變量的經常使用做用域有3種:orm

1> @public 全局均可以訪問
2> @protected 只能在類內部和子類中訪問
3> @private 只能在類內部訪問
htm

比Java少了一種做用域:包權限做用域,緣由很明顯:OC沒有包名的概念。

2、用Xcode建立第一個OC的類

 1.右擊項目文件夾或者文件,選擇"New File"

 

2.選擇Cocoa的"Objective-C class"

 

3.輸入類名和選擇父類

這裏的類名爲Student,父類是NSobject

 

4.建立完畢後,項目中多了兩個文件

* Student.h是類的聲明文件,Student.m是類的實現文件

* 默認狀況下,這2個文件的文件名跟類名一致

* 編譯器只會編譯.m文件,並不會編譯.h文件

3、第一個類的代碼解析

1.Student.h - 類的聲明文件

1 #import <Foundation/Foundation.h>
2 
3 @interface Student : NSObject
4 
5 @end

1> 看第3行,OC中使用關鍵字@interface來聲明一個類,@interface後面緊跟着類名Student。

2> 類名Student後面的冒號":"表示繼承,即第3行代碼的意思是Student繼承自NSObject。

3> 由於NSObject被聲明在Foundation.h中,因此在第1行用#import包含了Foundation.h文件。

4> 第5行的@end表示類的聲明結束了。@interface和@end是配套使用的。

2.Student.m - 類的實現文件

1 #import "Student.h"
2 
3 @implementation Student
4 
5 @end

1> 看第3行,OC中使用關鍵字@implementation來實現一個類。@implementation後面緊跟的類名,表示究竟要實現哪個類。

2> 由於Student這個類是聲明在Student.h中的,因此在第1行用#import包含了Student.h文件。若是你不包含Student.h,第3行代碼確定報錯,由於它根本不知道Student是個什麼鬼東西。

3> 第5行的@end表示類的實現結束了。@implementation和@end是配套使用的。

4、添加成員變量

正常狀況下,咱們都是把成員變量定義在頭文件中,也就是類的聲明文件(.h)中

1.給Student添加一個成員變量

#import <Foundation/Foundation.h>
@interface Student : NSObject{
  int age;  // 年齡
}

@end

1> 第4行定義了一個int類型的成員變量age,age的默認做用域是@protected,便可以在Student類內部和子類中訪問

2> 成員變量必須寫在大括號{ }裏面


2.設置成員變量的做用域

接下來給Student增長几個不一樣做用域的成員變量

#import <Foundation/Foundation.h>

@interface Student : NSObject {
    int age; // 年齡
    
    @public
    int no; // 學號
    int score; // 成績
    
    @protected
    float height; // 身高
    
    @private
    float weight; // 體重
}

@end

一共有5個成員變量,其中

@public做用域的有:no、score

@protected做用域的有:age、height

@private做用域的有:weight

 

5、添加方法

前面咱們定義了一個成員變量age,它的做用域是@protected,外界不能直接訪問它。爲了保證面向對象數據的封裝性,咱們能夠提供age的get方法和set方法,讓外界間接訪問age。接下來在Student中添加age的get方法和set方法

#import <Foundation/Foundation.h>

@interface Student : NSObject {
    int age; // 年齡
    
    @public
    int no; // 學號
    int score; // 成績
    
    @protected
    float height; // 身高
    
    @private
    float weight; // 體重
}

// age的get方法
- (int)age;

// age的set方法
- (void)setAge:(int)newAge;

@end

1> 第18行聲明瞭age的get方法,方法名就叫作age,OC建議get方法的名字跟成員變量保持一致(若是是在Java中,就應該叫作getAge)

2> 第18行最面的 - 表示這是一個動態方法( + 則表示靜態方法)。age前面的(int)表示方法的返回值爲int類型,方法的返回值參數類型都須要用小括號()包住

3> 第21行聲明瞭age的set方法,前面的 - 表示動態方法,(void)表示方法沒有返回值

4> 在OC方法中,一個冒號:對應一個參數。因爲第21行age的set方法接收一個int類型的參數,參數名爲newAge,因此(int)newAge前面有一個冒號:

5> 必定要記住:一個冒號:對應一個參數,並且冒號:也是方法名的一部分。所以第21行set方法的方法名是setAge:,而不是setAge


再加大一下難度,假如增長一個方法能夠同時設置age和height,那麼就應該這樣寫:

-(void)setAge:(int)newAge andHeight:(float)newHeight;

* 這個方法是動態方法、沒有返回值,接收2個參數,因此有2個冒號:

* 這個方法的方法名是setAge:andHeight:

* 其實andHeight是能夠省略的,它只是爲了讓方法名念起來通順一點,也讓(float)newHeight前面的冒號:不那麼孤單

2.在Student.m中實現方法

前面已經在Student.h中聲明瞭3個方法,接下來一一實現它們

#import "Student.h"
@implementation Student

// age的get方法
-(int)age{
 // 直接返回成員變量age
 return age;
 }
 
// age的set方法
-(void)setAge:(int)newAge{
  // 將參數賦值給成員變量age
  age = newAge;
}

// 同時設置age和Height的值
-(void)setAge:(int)newAge andHeight:(float)newHeight{
   age = newAge;\
   height = newHeight;
 }
 
@end

第6行對age方法進行了實現,第12行對setAge:方法進行了實現,第18行對setAge:andHeight:方法進行了實現

6、跟Java的比較

若是是在Java中,一個Student.java文件就能夠搞定成員變量和方法

public class Student {
    protected int age;
    protected float height;
    
    public int no;
    public int score;
    
    private float weight;

    /**
     * age的get方法
     */
    public int getAge() {
        return age;
    }
    
    /**
     * age的set方法
     */
    public void setAge(int newAge) {
        age = newAge;
    }
    
    /**
     * 同時設置age和height
     */
    public void setAgeAndHeight(int newAge, float newHeight) {
        age = newAge;
        height = newHeight;
    }
}


7、建立對象

前面已經定義了一個Student類,成員變量和方法都有了,接下來看一下怎麼使用這個類建立對象。

因爲OC程序的入口點是main函數,因此在main.m文件中演示Student類的使用。

先上完整代碼

#import <Foundation/Foundation.h>
#import "Student.h"

int main(int argc, const char * argv[]){
   @autoreleasepool{
   Student *stu = [[Student alloc] init];
   
   [stu release];
  }
  return 0;
}

1.包含Student.h

由於要用到Student這個類,因此在第2行包含了它的頭文件

#import "Student.h"

2.建立對象

1> 在Java中是使用關鍵字new來建立對象,好比new Student(),其實這句代碼作了2件事:

  • 給對象分配存儲空間

  • 調用Student的構造方法進行初始化

2> 在OC中建立對象也須要按順序作上面所述的2件事

1)調用Student類的靜態方法alloc分配存儲空間

Student *stu = [Student alloc];

  • OC是方法調用是用中括號[ ],方法調用者寫在括號左側,方法名寫在括號右側,中間留點空格。所以上面是調用了Student類的靜態方法alloc

  • 上面調用的alloc方法會返回分配好內存的Student對象,在等號左邊用了一個指向Student類型的指針變量stu來接收這個對象,注意stu左邊的*。全部OC對象都是用指針變量來接收的,若是你不瞭解指針,你記住下面這點就好了:利用類名定義一個變量時,類名後面必定要帶個*號。

  • alloc方法是這樣聲明的:

+ (id)alloc;

能夠看到,它的返回值類型是id,這個id表明任何指針類型,你能夠暫時理解爲:id能夠表明任何OC對象,相似於NSObject *。


2)調用Student對象的構造方法init進行初始化

前面調用alloc方法返回的Student對象stu是不能正常使用的,由於僅僅是分配了內存,並無進行初始化,接下來調用對象的init方法進行初始化


stu = [stu init];

看清楚了,因爲init是動態方法因此這裏使用stu變量來調用,並非使用類名來調用。init會返回已經初始化完畢的對象,再次賦值給了stu變量。這時候的Student對象stu才能正常使用。

注:動態方法可使用對象來調用,而靜態方法只能用類名來調用 ,[Student alloc] 如此方法。

3)其實,咱們最多見的作法是將alloc和init連起來使用:

Student *stu = [[Student alloc] init];

相信有面向對象開發經驗的你一眼就能看懂了,在main.m完整代碼的第7行

注意:Student *stu  中的Student爲指針變量類型,如 C語言中前邊的指針變量的類型Int同樣:

int b = 10;

int *p = &b;

3.銷燬對象

因爲OC不支持垃圾回收,所以當再也不使用某個對象時,須要調用對象的release方法釋放此對象。咱們在第9行銷燬了stu對象

[stu release];

這個release方法在這裏調用一次便可,不要以爲多調用多幾回,對象就會釋放地乾淨一點,這樣作會很危險,容易形成野指針錯誤。

4.其餘

1> 也能夠調用靜態方法new快速建立一個對象

1 Student *stu = [Student new];
2 
3 [stu release];

不過咱們仍是習慣使用alloc和init來建立對象

2> 前面我們調用了Student的alloc、init、new方法,可是你會發現Student.h中並無聲明這些方法,爲何可以調用呢?緣由很簡單,這些方法都是父類NSObject的,子類固然能夠調用父類的方法。


8、訪問公共成員變量和方法

前面已經成功建立了一個Student對象,接下來訪問一下它的公共變量和方法。

#import <Foundation/Foundation.h>
#import "Student.h"

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        Student *stu = [[Student alloc] init];
        
        // 訪問公共變量no
        stu->no = 10;
        
        // 調用setAge方法設置變量age的值
        [stu setAge:27];
        
        // 調用setAge:andHeight:方法同時設置變量age和height的值
        [stu setAge:20 andHeight:14.2f];
        
         // 訪問公共變量no
        int no = stu->no;
        // 調用age方法獲取變量age的值
        int age = [stu age];
        
        // 打印no和age的值
        NSLog(@"no is %i and age is %i", no, age);
        
        [stu release];
        
      }
      return 0;
  }

1.第7行建立了Student對象,第26行銷燬了對象

2.第10行和第19行訪問了Student對象的公共成員變量no,若是不是公共變量,不能像這樣直接訪問。注意訪問方式:對象->成員變量

3.第13行調用了Student對象的setAge:方法,傳入參數27修改了成員變量age的值

4.第16行調用了Student對象的setAge:andHeight:方法,同時修改了成員變量age和height的值

5.第21行調用了Student對象的age方法獲取成員變量age的值

6.第24行輸出了age和no的值,輸出結果:

2013-04-06 21:54:56.221 第一個OC程序[1276:303] no is 10 and age is 28

 

注:本文轉自M了個J博客。

相關文章
相關標籤/搜索