看官们,封装是面向对象的核心思想之一,在OC中主要是通过类来实现。封装就是通过类把各种类型的变量和方法(函数),封装到类内部,使用时通过类或者类的对象(实例)来使用。这样可以隐藏类的细节,并且提供专门的方法来使用被封装的变量。
这次我们先上代码,在代码中我们使用注释的方式介绍了各段代码的含义。我们结合代码来做介绍。
#import<Foundation/Foundation.h>
//声明类Phone,父类是NSObject
@interface Phone : NSObject
//声明属性(成员变量)
@property char *name;
@property int size;
@property int test;
//声明方法(成员函数),三个实例方法,参数个数依次为0,1,2。
-(void) makeCall;
-(void) playMusic:(char *)str;
-(int) connect:(int)valueA and:(int)valueB;
//声明方法(成员函数),一个类方法,而且不带参数
+(void) takePicture;
//声明类Phone结束
@end
//实现类Phone
@implementation Phone
@synthesize size;
@synthesize name;
int priValue;
//实现初始化方法
-(instancetype) init {
self = [super init];
if(self){
name = "no name";
size = 0;
_test = 0;
}
return self;
}
//实现方法
-(void) makeCall {
NSLog(@"make call");
}
-(void) playMusic:(char *)str {
NSLog(@"play music of %s",str);
}
-(int) connect:(int)valueA and:(int)valueB {
NSLog(@"connect %i, and %i",valueA,valueB);
return (valueA + valueB);
}
+(void) takePicture {
NSLog(@"takePicture");
}
-(void) privateFunc {
NSLog(@"this is privateFunc");
}
//实现类Phone结束
@end
//主程序,演示创建类的实例,以及类中属性和方法的使用
int main() {
//调用init初始化方法初始化实例
Phone *p1 = [[Phone alloc] init];
// Phone *p1 = [Phone new];
//使用点操作属性,输出初始化后的属性值
NSLog(@"name = %s",p1.name);
NSLog(@"size = %d",p1.size);
NSLog(@"test = %d",p1.test);
//使用点操作属性,然后输出修改后的属性值
p1.name = "apple";
NSLog(@"name %s",p1.name);
//不能使用私有属性,会有编译错误
// NSLog(@"%d",p1.priValue);
//使用消息传递来操作属性,其中使用了属性的getter和setter方法
[p1 setName:"Huawei"];
NSLog(@"name %s",[p1 name]);
//使用消息传递来操作实例方法
[p1 makeCall];
[p1 connect:1 and:2];
//使用消息传递来操作类方法
[Phone takePicture];
return 0;
}
代码中类分为声明的实现两个部分,声明使用@interface关键字,实现使用@implementation关键字。声明主要是定义类中封装的属性和方法;实现主要是对类中方法的实现,当然在实现部分中也可以定义类的属性。另外,在声明时使用了父类,大家先了解下就可以,我们在后面章回中介绍继承时会做详细的介绍。类的声明和实现部分都以@end来表示结束。
在代码中我们定义并且实现了名叫Phone的类,类中封装了三个变量四个方法,为了方便解释,在以后的博客中,我们把被封装的变量统一称作属性(也有叫成员变量的);被封装的方法统一称作方法。属性和方法可以在类声明中定义,也可以在类实现中定义,不过不同的位置有不同的含义。到底有什么含义?我们暂且不表。
类中的属性有私有和公有两种访问权限,私有权限表示它们只能类内部使用,公有权限表示可以通过类的实例来使用。例如代码中的priValue变量就拥有私有权限,我们只能在类内部访问它,如果使用对象访问它会产生编译错误,因此我们在代码中注释了它的使用。而size等其它三个属性就拥有公有权限,可以通过Phone类的实例p1来访问,这是我们最常使用的内容。造成属性不同权限的原因在于定义属性的位置不同,当属性定义在类声明中时拥有公有权限,定义在类实现中时拥有私有权限。现在回头看看,我们刚才不表的内容是不是知道原因了?
类中的方法有两种归属方式:一种是属于类的对象(实例)所有,定义方法时使用减号来标记;另外一种是属于类本身所有,定义方法时使用加号来标记。在代码中takePicture方法是类的方法,我们可以通过类来直接使用它,其它方法都是类对象的方法,只能通过类的对象p1来使用。
我们接下来介绍一下属性的setter和getter操作,通过它们可以操作类中的属性。在类声明中使用@property,在类实现时使用@synthesize关键字,这样就会生成属性的setter和getter方法,我们可以通过类的对象来使用setter和getter方法,在代码中name属性就是一个例子,不过getter方法的名字和属性名字一样,不像setter方法一样有set关键字,它没有get关键字。除了这两种方法外,还可以使用点操作符来访问属性,这个我们在代码中有演示。不过我还是推荐使用setter和getter方法。
看官们,本章回中介绍了许多内容,我们在这里做统一的总结:
- 1.封装的特点隐藏私有的内容,让大家忽略类的细节,同时开放出专门的方法,方便我们操作变量;
- 2.封装通过类来实现,类分为声明和实现两个部分;声明部分主要定义类的变量和方法,实现部分主要实现类的方法;
- 3.属性拥有公有和私有两种权限,私有权限的属性只能在类内使用,公有权限的属性可以通过类的对象来使用,这是最常用的方式;
- 4.方法拥有两种归属方式:一种属于类所有,另外一种属于类的对象所有;
- 5.通过使用synthesize关键字来修饰属性,可以自动生成属性的getter和setter方法;
- 6.属性可以使用getter和setter方法操作,也可以使用点操作符来操作,不过我们推荐使用前者;