作为一个Javaer,你肯定已经了解了类、对象和方法的相关概念。如果你现在对类和对象还没一个深刻的认识,强烈建议先去了解一下OO的相关知识。

Objective-C如何定义一个类

比如我们把手机就可以看成一个类,手机具有颜色、品牌、操作系统等属性。同时也具有打电话、发短信等功能(行为)。在Java中,我们用代码可以表示为:

package com.demo;

/**
 * 手机类
 * @author liuzc
 */
public class Phone {

	private String color;  //颜色
	private String os;     //系统
	private String brand;  //品牌

	/******* Getter & Setter *******/
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	public String getOs() {
		return os;
	}
	public void setOs(String os) {
		this.os = os;
	}
	public String getBrand() {
		return brand;
	}
	public void setBrand(String brand) {
		this.brand = brand;
	}

	public void makeCall(String number){
            System.out.println("正在呼叫:"+number);
        }

       public void sendSMS(String number,String content){
          System.out.println("发送短信给"+number+" 内容为:"+content); }
         }

下面我们先给出Objective-C中的代码,然后再来进一步说明。

类声明(接口)

//  Phone.h
//  OCStudy_01
//
//  Created by Liuzc on 12-12-5.
//  Copyright (c) 2013年 http://liuzhichoa.com. All rights reserved.
//

#import  <Foundation/Foundation.h>

@interface Phone : NSObject{
    NSString *color;
    NSString *brand;
    NSString *os;
}

-(NSString*) color;
-(NSString*) brand;
-(NSString*) os;
-(void) setColor:(NSString*) _color;
-(void) setBrand:(NSString*) _brand;
-(void) setOs:(NSString*) _os;
-(void) makeCall:(NSString*) number;
-(void) sendMsg:(NSString*) number AndContent:(NSString*) content;

@end

类实现

//
//  Phone.m
//  OCStudy_01
//
//  Created by Liuzc on 12-12-5.
//  Copyright (c) 2013年 http://liuzhichoa.com. All rights reserved.
//

#import "Phone.h"

@implementation Phone

-(NSString*) color{
    return color;
}

-(NSString*) brand{
    return brand;
}

-(NSString*) os{
    return  os;
}
-(void) setColor:(NSString*) _color{
    color = _color;
}
-(void) setBrand:(NSString*) _brand{
    brand = _brand;
}

-(void) setOs:(NSString*) _os{
    os=_os;
}

-(void) makeCall:(NSString*) number
{
    NSLog(@"正在呼叫: %@",number);
}

-(void) sendMsg:(NSString *)number AndContent:(NSString *)content{
    NSLog(@"发送短信给 %@ ,内容为:%@",number,content);
}

@end

Phone.h是头文件,Phone.m是Objective-C的类文件,在头文件中,我们需要编写@interface部分,在Phone.m文件中编写类的实现.当然,你把代码写在一个文件里也是可以的,但我们一般不推荐这样做。例如下面的代码也可以正常编译:

Phone.m

//
//  Phone.m
//  OCStudy_01
//
//  Created by Liuzc on 12-12-5.
//  Copyright (c) 2013年 http://liuzhichoa.com. All rights reserved.
//

#import  <Foundation/Foundation.h>

@interface Phone : NSObject

-(NSString*) color;
-(NSString*) brand;
-(NSString*) os;
-(void) setColor:(NSString*) _color;
-(void) setBrand:(NSString*) _brand;
-(void) setOs:(NSString*) _os;
-(void) makeCall:(NSString*) number;
-(void) sendMsg:(NSString*) number AndContent:(NSString*) content;

@end

@implementation Phone
{
    NSString *color;
    NSString *brand;
    NSString *os;
}

-(NSString*) color{
    return color;
}

-(NSString*) brand{
    return brand;
}

-(NSString*) os{
    return  os;
}
-(void) setColor:(NSString*) _color{
    color = _color;
}
-(void) setBrand:(NSString*) _brand{
    brand = _brand;
}

-(void) setOs:(NSString*) _os{
    os=_os;
}

-(void) makeCall:(NSString*) number
{
    NSLog(@"正在呼叫: %@",number);
}

-(void) sendMsg:(NSString *)number AndContent:(NSString *)content{
    NSLog(@"发送短信给 %@ ,内容为:%@",number,content);
}

@end

下面我们通过一张图来说明定义一个类的接口@interface部分的语法。

Declaring_Class_Syntax
Declaring_Class_Syntax

定义新类时,在Java中,当一个类的父类为Object时,我们不需要指明 ClassName extends Object。而在Objective-C中,需要显示的指明该类的父类,哪怕该类的父类为NSObject。其次还必须定义在处理该类的对象时将要用到的各种操作或是方法类型。

同Java一样,类名通常以大写字母开头,尽管没有要求一定要这样做,但这种约定能使他人更容易读懂你的程序。还有一个容易忽视却又很重要的细节,在Objective-C中,所有的类名都必须是唯一的(Class Names Must Be Unique)。也许现在你已经明白为什么使用XCode新建项目时,为什么推荐你填写前缀了。For this reason, it’s advisable to prefix the names of any classes you define。

在类的声明中,使用@interface定义类的接口部分。在Java中,interface是定义接口的关键字,可此interface非彼interface,实际上我们所理解的Java中的接口(interface),在Objective-C中称为协议(protocol)”)。

同样,我们通过一张图来说明类的实现@implementation部分的语法

Definitions_Class_Syntax
Definitions_Class_Syntax

@implementation部分包含声明在@interface部分的方法的实际代码。实现代码中必须导入它的接口文件,写在代码的第一行。

NewClassName表示的名称与@interface中的名称相同,可以在类的名称之后使用冒号,@implementation NewClassName: ParentClassName,但这里与Java中一样,它是可选的,而且通常并不这样做。

Objective C中类分为两个文件,一个是.h文件,一个是.m文件 .h文件存放函数的声明,类声明使用关键字@interface @end .m文件存放类的具体实现,类实现使用关键字@implementation @end

声明对象和对象初始化

上面我们定义了一个类,并声明了几个属性和方法.那么我们如何使用我们定义的类呢?也就是说如何声明和初始化一个对象?在java中我们这样做.

 Phone phone = new Phone();
 phone.setOs("iOS");
 phone.setColor("white");
 phone.setBrand("iPhone");

 //调用打电话的方法
 phone.makeCall("10086");

 //调用发短信的方法
 phone.sendSMS("10086","什么时候和Apple合作出iPhone移动3G版啊?");

在java中实例化一个对象我们使用new关键字,在Objective-C中我们也可以使用new关键字实例化一个类,不过语法与java有点区别:

Phone* phone =[Phone new]; 

有点C/C++基础的应该知道”*“代表的是指针变量,[Phone new]实例上是调用Phone的new方法,(你也许会诧异,我们在Phone中没有定义new方法啊,事实上new是NSObject中定义的方法,因为Phone继承了NSObject,所以也继承了new方法,想要了解Objective-C中更多关于继承的知识,可以查看这里).

如果你查看网上一些Objective-C的开源代码,你会发现在实例化一个类时,大多使用的是下面的语法:

Phone* phone = [[Phone alloc] init];

甚至看到这样把两者拆开的写法:

Phone* phone = [Phone alloc];
[phone init]

通过调用这两个方法,完成了对一个对象的声明和初始化,其中alloc是为对象申请了内存空间,init则完成了对象的初始化.在完成对象声明和初始化以后,就可以调用对象的方法:

[phone setOs:@"iOS"];
[phone makeCall:@"10086"];

你也许就会问了,既然使用new和使用alloc init都可以,那我们通常应该使用哪一种,或者说这两种方式有什么区别呢?在回答这个问题之间,我们先来介绍Objective-C中的构造函数。

Objective-C的构造函数

在java中,当我们在实例化一个对象并对成员变量赋值时,我们通常使用构造函数,类似于:

Phone phone = new Phone("iOS");

当然构造函数需要我们自己重构.在Objective-C中,构造函数可以使用任何方式命名,但是通常,将他们命名为 init 。构造方法返回对象的一个指针,我们可以通过调用超类的 init 方法来获取这个指针,超类是当前的类所派生自的类,也就是当前类的父类,这里通常是 NSObject 类。

-(Phone *) initWithOs:(NSString *)_os{
   self = [super init];
   if(self){
     [self setOs:_os];
   }
   return self;
}
-(Phone *)initWithOs:(NSString *)_os andWithColor:(NSString *)_color{
   self = [super init];
   if(self){
     [self setOs:_os];
     [self setColor:_color]
   }
   return self;
}

我们再来初始化Phone时,就可以使用下面的语句:

Phone* phone =[[Phone alloc] initWithOs:@"iOS"];

或者:

Phone* phone =[[Phone alloc] initWithOs:@"iOS" andWithColor:@"black"];

但是如果这里我们使用new的话,就无法做到这一点.所以你现在应该大致清楚了new和alloc+init的区别.

  • new doesn’t support custom initializers (like initWithString)
  • alloc-init is more explicit than new

所以默认情况下, new和alloc+init是没有什么区别的,new = alloc+init 毫不夸张的说,+new的实现应该是这样:

+ (id) new
{
    return [[self alloc] init];
}

Mac Developer Library中关于new的介绍也说明了这点:

This method is a combination of [alloc](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/clm/NSObject/alloc) and [init](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/init). Like [alloc](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/clm/NSObject/alloc), it initializes the isa instance variable of the new object so it points to the class data structure. It then invokes the [init](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/init) method to complete the initialization process.

这一讲关于Objective-C中类的介绍就到这里,下一讲将介绍Objective-C中的属性.