oc面向对象三大特性之一 <封装>

oc面向对象三大特性之一 <封装>

一 . 封装概述

1> 什么是封装? --- 封装性就是隐藏实现细节,,仅对外公开接口。

** 延伸出答案可以很多很多,意思大概一样

2> 为什么要进行封装?

请看以下代码存在的问题?

// 1成员变量是public的,也就是公开的,我们不能控制外界如何赋值, 外界有可能赋值一些脏数据
@interface Gun : NSObject
{
    @public// 公开成员变量
    int _bulletCount;// 子弹数量
}
@end

// 可以利用封装来解决这个问题
// 封装:是指隐藏对象的属性和实现的细节,仅对外提供公共的访问方法

// 成员变量是public的,也就是公开的,我们不能控制外界如何赋值, 外界有可能赋值一些脏数据

@interface Gun : NSObject
{
    @public// 公开成员变量
    int _bulletCount;// 子弹数量
}
@end

// 可以利用封装来解决这个问题
// 封装:是指隐藏对象的属性和实现的细节,仅对外提供公共的访问方法

1> 类是数据与功能的封装,数据就是成员变量,功能就类方法或对象方法

2> 对数据的封装,也就是对成员变量的封装

3> 不封装的缺点:当一个类把自己的成员变量暴露给外部的时候,那么该类就失去对该成员变量的管理权,别人可以任意的修改你成员变量。

4> 封装就是将数据隐藏起来,只能用此类的方法才可以读取或者设置数据,不可被外部任意修改是面向对象设计本质。降低了数据被误用的可能性! ,提高代码的灵活性

3> 封装的好处

+> 将变化隔离

+> 提高安全性

原则

+> 将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供公共的方法对其访问

二. 封装中不得不谈的getter/setter方法

1> setter方法

作用:用来设置成员变量,可以在方法里面过滤掉一些不合理的值

> 命名规范:

1> 必须是对象方法

2> 返回值类型为void

3> 方法名必须以set开头,而且后面跟上成员变量名去掉”_” 首字母必须大写

4> 必须提供一个参数,参数类型必须与所对应的成员变量的类型一致

5> 形参名称和成员变量去掉下划线相同

> 举例:

如:如果成员变量为int _age 那么与之对象seter方法为
-(void) setAge: (int) age;

** setter方法的好处

a. 不让数据暴露在外,保证了数据的安全性

b. 对设置的数据进行过滤

2> getter方法

> 作用:为调用者返回对象内部的成员变量的值

> 命名规范:

1> 必须是对象方法

2> 必须有返回值,返回值的类型和成员变量的类型一致

3> 方法名必须是成员变量去掉下划线

4> 一定是没有参数的

> 举例

如:如果成员变量为int _age 那么与之对象geter方法为

- (int) age;

> getter方法的优点:

+> 可以让我们在使用数据的拿到数据之前对数据进行加工;

+> 比如双十一活动,我们希望对全线商品的价格在原来的价格基础上打五折,那么我们只要去改成品类的价格的getter方法就可以了,让他返回的值为价格 * 0.5

3> getter/setter方法注意

1> 在实际的开发中,不一定set和get方法都会 供,如果内部的成员变量比如学生的学号或计算出来的数据这样的数据只允许外界读取,但是不允许修改的情况,则通常只 供get方法而不 供set方法。

2> 成员变量名的命名以下划线开头,get方法名不需要带下划线,

3> 成员变量名使用下划线开头有两个好处

a. 与get方法的方法名区分开来

b. 可以和一些其他的局部变量区分开来,下划线开头的变量,通常都是类的成员变量。当我看到以下划线开头变量,那么他一定是成员变量

三. 又不得不谈的点语法

1> 点语法的本质

> 其实点语法的本质还是方法调用

> 当使用点语法时,编译器会自动展开成相应的方法

- 当点语法使用在 “=“赋值符号左侧的时候,点语法会被展开为setter方法的调用,其他情况(等号右侧、直接使用)为点语法展开为getter方法的调用

2> 点语法注意

1> 点语法的本质是方法的调用,而不是访问成员变量,当使用点语法时,编译器会自动展开成相 应的方法调用。
2> 切记点语法的本质是转换成相应的对setter和getter方法调用,如果没有set和get方法,则不能使用点语法。
3> 不在要再getter 与 setter方法中使用本属性的点语法

- (void) setAge:(int)age {
    // 下面的代码会引发死循环
    self.age = age;
        //编译器展开后 [self setAge:age]
}

- (int) age {
    // 下面的代码会引发死循环
    return self.age;
          // 编译器展开后 [self   age]
}

四. 和不得不谈的self关键字

> OC语言中的self,就相当于C++、Java中的this指针。

1> 要搞清楚self你搞清楚什么是成员变量,什么对象方法,什么是类方法

2> 成员变量:成员变量是一个实例对象的具体状态特征,并且这些状态特征是可以改变的,如张三的年龄,身高,体重等

3> 对象方法:一个实例对象的行为,比如张三具有吃的行为,张三做出这样行为的时候,有可能会影响,自身的某些状态特征,比如张三吃可能会增加张三体重和身高。

4> 类方法:类方法是某个类的行为,可以直接通过类名调用;如果在类方法中需要使用某些数据,必须通过参数传入;它不能访问成员变量。

1> 类方法中的self

1> 在整个程序运行过程中,`一个类有且仅有一个类对象`。

2> 通过`类名`调用方法就是给这个`类对象`发送消息。

3> 类方法的self就是这个类对象

4> 在类方法中可以通过self来调用其他的类方法

5> 不能在类方法中去调用对象方法或成员变量,因为对象方法与成员变量都是属于具体的实例对象的。

2> 对象方法中的self

1> 在整个程序运行过程中,`对象可以有0个或多个`

2> 通过`对象`调用方法就是给这个`对象`发送消息

3> 对象方法中self就是调用这个方法的当前对象。

4> 在对象方法中,可以通过self来调用本对象上的其他方法

5> 在对象方法中,可以通过self来访问成员变量

3> 全局变量成员变量局部变量

1> 全局变量:只要是有声明它的地方都能使用

2> 成员变量:在能在本类的对象方法中使用

3> 局部变量:只能在本函数或方法中使用

4> 从作用域的范围来看:全局变量 > 成员变量 > 局部变量

5> 当不同的作用域中出现了同名的变量,内部作用域的变量覆盖外部作用域变量,所以同名变量的覆盖顺序为:局部变量覆盖成员变量,成员变量覆盖全局变量

6> 如果在对象方法中出现与成员变量同名的局部变量,如果此时想使用该成员变量可以通过self->成员变量名的方式

4> self总结

谁调用self所在的方法,那么self就是谁

&& self在类方法中就是这个类的类对象,全局只有一个,可通过self本类中的其他类方法,但是不能通过self来调用对象方法或访问成员变量

&& self在对象方法中,就是调用这个方法的那个对象, 可以通过self调用其他本类中其他的对象方法,访问成员变量,但不能通过self调用本类的类方法。

** 通过self调用方法的格式:[self 方法名];

** 通过self访问成员变量格式:self->成员变量名

5> self使用注意

> 同时有对象方法和类方法存在的时候,self不会调错

> self只能在方法中使用;不要使用self来调用函数,也不可以在函数内部使用self;

> 使用self调用本方法,导致死循环调用。

发布于 2015-08-20

文章被以下专栏收录