码迷,mamicode.com
首页 > 其他好文 > 详细

OC脱变第三天

时间:2015-07-29 22:37:21      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:

主要内容概括

标号主题内容
封装 面向对象三大特性;封装的概念/原因/好处/原则
*getter和setter setter / getter方法;注意点
自定义代码段 如何自定义代码片段 / 导入代码片段
*点语法 点语法基本使用/本质/注意
self关键字 类方法与对象方法中的self/全局变量成员变量局部变量/总结/使用注意
*继承 继承基本概念/OC中的继承关系以及如何实现继承/相关特性
Super super基本概念/作用/使用场景
*多态 多态概念/条件/优点/实现多态的原理/注意点
实例变量修饰符 实例变量的作用域/变量修饰符在子类中的访问/实例变量作用域使用注意事项
description description基本概念/重写的方法/陷阱

一.封装

1.面向对象三大特性
  • 封装性
  • 继承性
  • 多态性
2.什么是封装
  • 封装性就是隐藏内部实现的细节,,仅对外公开接口。
  • 规范
    • 一般情况下不会对外直接暴露成员变量,都会提供一些共有的方法进行赋值,成员变量都需要封装起来
    • 当成员变量进行封装后,还要提供一个方法返回成员变量的值
3.为什么要进行封装?
  • 以下代码存在的问题?
// 1成员变量是public的,也就是公开的,我们不能控制外界如何赋值, 外界有可能赋值一些脏数据
@interface Gun : NSObject
{
    @public// 公开成员变量
    int _bulletCount;// 子弹数量
}
@end

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

 

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

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

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

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

4.封装的好处
  • 好处

    • 将变化隔离
    • 提高数据的安全性
  • 原则

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

二.getter和setter

  • 成员变量前加下划线是为了区分成员变量和形参
1.setter方法
  • 作用:用来设置成员变量,可以在方法里面过滤掉一些不合理的值

  • 命名规范:

    • 必须是对象方法
    • 必须没有返回值
    • 返回值类型为void
    • 方法名必须以set开头,而且后面跟上成员变量名去掉”_”,首字母必须大写
    • 必须提供一个参数,参数类型必须与所对应的成员变量的类型一致
    • 形参名称和成员变量去掉下划线相同
       如:如果成员变量为int _age 那么与之对应seter方法为
      (void) setAge: (int) age;
      
      (void) setAge: (int) age { _age = age; } 
  • setter方法的好处

    • 不让数据暴露在外,保证了数据的安全性
    • 对设置的数据进行过滤
    • 可以监听属性的变化
//只要_max或者_min发生变化就重新计算_average,否则不重新计算
- (void)setMax:(int)max
{

    _max = max;
    _average = (_max + _min) / 2;
}
- (void)setMin:(int)min
{
    _min = min;
    _average = (_max + _min) / 2;
}
- (int)average
{
    _average = average;
}
2.getter方法
  • 作用:为调用者返回对象内部的成员变量的值

  • 命名规范:

    • 必须是对象方法
    • 必须有返回值,返回值的类型和成员变量的类型一致
    • 方法名必须是成员变量去掉下划线
    • 一定是没有参数的
  • 举例

    如:如果成员变量为int _age 那么与之对应geter方法为
    - (int)age;
    - (int)age
    {
        return _age;
    }
  • getter方法的优点:
    • 可以让我们在使用getter方法获取数据之前,对数据进行加工;
    • 比如双十一活动,我们希望对全线商品的价格在原来的价格基础上打五折,那么我们只要去改成品类的价格的getter方法就可以了,让他返回的值为价格 * 0.5
3.getter/setter方法注意
  • 在实际的开发中,不一定set和get方法都会提??供,如果内部的成员变量,比如学生的学号或计算出来的数据。这样的数据只允许外界读取,但是不允许修改的情况,则通常只提??供get方法而不??提供set方法 。

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

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

    • 与setter和getter方法的方法名区分开来
    • 可以和一些其他的局部变量区分开来,下划线开头的变量,通常都是类的成员变量。当看到以下划线开头的变量,那么一定是成员变量
  • 如果某一个属性只提供getter方法,称为只读属性
  • 如果某一个属性只提供setter方法,称为只写属性
  • 如果某一个属性不提供getter和setter方法,称为私有属性
  • 如果某一个属性提供了getter和setter属性,称为可读可写属性

三.自定义代码段

1.如何自定义代码片段
  • 将代码拖拽到code区域
  • 配置快捷键等信息
  • 使用快捷键
  • 注意
    • <#随便写井号>
2.如何导入代码片段
  • 将下载好的代码片段拷贝到:/Users/zhangxiaoliang/Library/Developer/Xcode/UserData/CodeSnippets

四. 点语法

  • 如果给属性提供了getter和setter方法,那么访问属性就多了一种方法,点语法
1.点语法基本使用
p.name = @"hmj";
p.age = 20;
p.height = 1.7;

NSLog(@"name  = %@, age = %i, height = %f", p.name, p.age, p.height);
2.点语法的本质
  • 点语法的本质是方法调用了setter和getter方法
  • 当使用点语法时,点语法是一个编译器的特性,会在程序翻译成二进制的时候,语法自动转换为setter和getter方法
  • 当点语法使用在“=“赋值符号左侧的时候,点语法会被展开为setter方法的调用,其他情况(等号右侧、直接使用)为点语法展开为getter方法的调用
    p.name = @"hmj";
    转换成
    [p setName:@"hmj"];
    
    NSLog(@"name  = %@, age = %i, height = %f", p.name, p.age, p.height);
    转换成
    [p name];
    [p age];
3.点语法注意
  • 点语法的本质是方法的调用,而不是访问成员变量,当使用点语法时,编译器会自动展开成相应的方法调用。

  • 点语法一般用于给成员变量赋值,如果不是给成员变量赋值一般情况下不建议使用,但也可以使用

  • 切记点语法的本质是转换成相应的对setter和getter方法调用,如果没有set和get方法,则不能使用点语法。

  • 不要在getter与setter方法中使用本属性的点语法,否则会引发死循环

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


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


五.self关键字

  • OC提??供了两个保留字self和super
    • OC语言中的self,就相当于C++、Java中的this指针。
  • 要理解什么是self,什么是成员变量,什么是对象方法,什么是类方法
  • 成员变量:成员变量是一个实例对象的具体状态特征,并且这些状态特征是可以改变的,如张三的年龄,身高,体重等
  • 对象方法:一个实例对象的行为,比如张三具有吃的行为,张三做出这样行为的时候,有可能会影响,自身的某些状态特征,比如张三吃可能会增加张三体重和身高。
  • 类方法:类方法是某个类的行为,可以直接通过类名调用;如果在类方法中需要使用某些数据,必须通过参数传入;它不能访问成员变量。
1.类方法中的self
  • self == 类
  • 在整个程序运行过程中,一个类有且仅有一个类对象
  • 通过类名调用方法就是给这个类对象发送消息,也可以用self来调用类方法
  • 类方法的self就是这个类对象
  • 在类方法中可以通过self来调用其他的类方法
  • 不能在类方法中去调用对象方法或成员变量,因为对象方法与成员变量都是属于具体的实例对象的。
2.对象方法中的self
  • self == 对象
  • 在整个程序运行过程中,对象可以有0个或多个
  • 通过对象调用方法就是给这个对象发送消息
  • 对象方法中self就是调用这个方法的当前对象。
  • 在对象方法中,可以通过self来调用本对象上的其他方法
  • 在对象方法中,可以通过self来访问成员变量
3.全局变量成员变量局部变量
  • 全局变量:只要是有声明它的地方都能使用
  • 成员变量:只能在本类和其子类的对象方法中使用
  • 局部变量:只能在本函数或方法中使用
  • 从作用域的范围来看:全局变量 > 成员变量 > 局部变量
  • 当不同的作用域中出现了同名的变量,内部作用域的变量覆盖外部作用域变量,所以同名变量的覆盖顺序为:局部变量覆盖成员变量,成员变量覆盖全局变量
  • 如果在对象方法中出现与成员变量同名的局部变量,如果此时想使用该成员变量可以通过self->成员变量名的方式
4.self使用场景
  • 可以用于对象方法之间进行相互调用
  • 可以用于类方法之间进行调用
  • 可以区分局部变量和全局变量
5.self总结
  • 谁调用self所在的方法,那么self就是谁
  • self在类方法中,就是这个类的类对象,全局只有一个,可通过self调用本类中的其他类方法,但是不能通过self来调用对象方法或访问成员变量
  • self在对象方法中,就是代表调用当前这个方法的那个对象,可以通过self调用本类中其他的对象方法,访问成员变量,但不能通过self调用本类的类方法。

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

  • 通过self访问成员变量格式:self->成员变量名
6.self使用注意
  • 同时有对象方法和类方法存在的时候,self不会调错
  • self会自动区分类方法和对象方法,如果在类方法中使用self调用对象方法,那么会直接报错
  • self只能在方法中使用;不要使用self来调用函数,也不可以在函数内部使用self;
  • 使用self调用本方法,导致死循环调用。
    + (void)openFlashLight
    {
        [self openFlashLight];
    }

六.继承

1.继承基本概念
  • 现实生活中的继承
  • 交通工具类是一个基类(也称做父类),通常情况下所有交通工具所共同具备的特性,如速度与额定载人的数量可。
  • 飞机类和汽车类的特性是由在交通工具类原有特性基础上增加而来的,那么飞机类和汽车类就是交通工具类的派生类(也称做子类)。以此类推,层层递增,这种子类获得父类特性的概念就是继承
2.OC中的继承关系
  • B类继承A类,那么B类将拥有A类的所有属性和方法(类方法和对象方法),此时我们说A类是B类的父类(超类),B类是A类的子类
  • C类继承B类,那么C类将拥有B类中的所有属性和方法,同时也包括B类从A类中继承过来的属性和方法,此时我们说B类是C类的父类,C类是B类的子类
3.OC中如何实现继承
  • 在声明子类的时候,在子类名称后面通过:父类名称 方式来实现继承
@interface 子类名称 : 父类名称

@end
4.方法重写
  • 在子类中实现与父类中同名的方法,称之为方法重写;
  • 重写以后当给子类发送这个消息的时候,执行的是在子类中重写的那个方法,而不是父类中的方法。
  • 如果想在子类中调用被子类重写的父类的方法,可以通过super关键字
  • 使用场景:当从父类继承的某个方法不适合子类,可以在子类中重写父类的这个方法。

注意:不能重写继承过来的属性

5.继承中方法调用的顺序
  • 1、在自己类中找
  • 2、如果没有,去父类中找
  • 3、如果父类中没有,就去父类的父类中
  • 4、如果父类的父类也没有,就还往上找,直到找到基类(NSObject)
  • 5、如果NSObject都没有就报错了(unrecognized selector sent to instance)
    • 如果找到了就执行这个方法,就不再往后查找了
6.继承的注意事项
  • 子类不能定义和父类同名的成员变量,私有成员变量也不可以;因为子类继承父类,子类将会拥有父类的所有成员变量,若在子类中定义父类同名成员变量 属于重复定义。
  • OC类支持单一继承,不支持多继承;也就是说一个类只能有一个直接父类
  • OC类支持多层继承,即A继承B,B继承C,C继承D......
  • 只有满足条件才可以用继承
    • 某某 is a 某某
  • 基类的私有属性能被继承,但不能在子类中访问。

    • OC中的继承是单继承:也就是说一个类只能一个父类,不能继承多个父类
    • 子类与父类的关系也称为isA(是一个继承)关系,我们说子类isA父类,也就是子类是一个父类,比如狗类继承动物类,那么我们说狗isA动物,也就是狗是一个动物。在如汽车继承交通工具,那么们说汽车isA交通工具,也就是汽车是一个交通工具
    • 不要发现多个类中有重复代码就抽取一个父类
  • 继承的优点

    • 提高代码的复用性
    • 可以让类与类之间产生关系,从而产生多态
  • 继承缺点

    • 耦合性太强(依赖性太强)

七.super

1.super基本概念
  • super是个编译器的指令符号,只是告诉编译器在执行的时候,去调谁的方法.
    • self是一个隐私参数;
    • super 并不是隐藏的参数,它只是一个“编译器指示符”,它和 self 指向的是相同的消息接收者
self refers to the object receiving a message in objective-C programming.

super is a flag that tells the compiler to search for the method implementation in a very different place. 
It begins in the superclass of the class that defines the method where super appears.
2.super的作用/使用场景
  • 1.在子类中直接调用父类中的某个方法,而self会先在自己的方法中找是否有这个方法,因而造成死循环
  • 2.super在对象方法中,那么就会调用父类的对象方法;super在类方法中,那么就会调用父类的类方法;可以利用super在任意方法中调用父类中的方法

  • 使用场合:

    • 在子类重写父类的方法的同时,还想保留父类的一些功能

八.多态

  • 多态的前提是继承
1.什么是多态?
  • 什么是多态:多态就是某一类事物的多种形态
    • 猫: 猫-->动物
    • 狗: 狗-->动物
  • 程序中的多态:父类指针指向子类对象

  • 优点

    • 提高代码的拓展性
2.多态的条件
  • 有继承关系
  • 子类重写父类方法
  • 父类指针指向子类对象
狗 *g = [狗 new];
动物 *a = [狗 new];//多态
猫 *c = [猫 new];
动物 *b = [猫 new];//多态
[b eat];//调用的是狗的方法
动态类型:
在编译时编译器只会检查当前类型对应的类中有没有调用的方法(有就编译成功,否则失败)
在运行时,系统会自动判断b的真实类型

 

  • 表现:
    • 当父类指针指向不同的对象的时候,通过父类指针调用被重写的方法的时候,会执行该指针所指向的那个对象的方法
3.多态的优点
  • 多态的主要好处就是简化了编程接口。它允许在类和类之间重用一些习惯性的命名,而不用为每一个新加的函数起一个新名字。这样,编程接口就是一些抽象的行为的集合,从而和实现接口的类的区分开来。

  • 多态也使得代码可以分散在不同的对象中而不用试图在一个函数中考虑到所有可能的对象。这样使得您的代码扩展性和复用性更好一些。当一个新的情景出现时,您无须对现有的代码进行改动,而只需要增加一个新的类和新的同名方法。

4.如何实现多态
  • Animal是父类,子类有Cat和Dog,子类分别重写了父类中的eat方法;实例化对象的时候可以用下面的方法:
Animal *animal = nil;

//实例化猫的对象
animal = [Cat new];
[animal eat];

//实例化狗的对象
animal = [Dog new];
[animal eat];
5.多态的原理
  • 动态绑定:
    • 动态类型能使程序直到执行时才确定对象的真实类型
    • 动态类型绑定能使程序直到执行时才确定要对那个对象调用的方法
    • 在编译时编译器只会检查当前类型对应的类中有没有调用的方法(有就编译成功,否则失败)
    • 在运行时,系统会自动判断对象的真实类型
  • OC不同于传统程序设计语言,它可以在运行时加入新的数据类型和新的程序模块:动态类型识别,动态绑定,动态加载
  • id类型:通用对象指针类型,弱类型,编译时不进行具体类型检查
6.多态的注意点
  • 1)如果存在多态,父类是可以访问子类特有的方法
    • 在多态中,如果父类指针指向子类的对象,如果想调用子类特有的方法必须强制类型转换为子类才能调用
假设 子类 Dog 有一个特有的方法bark
[dog bark];
Animal *an2 = [Dog new];
[(Dog*)an2 bark]; //把父类的指针,强制类型转换
  • 2)如果不存在多态,父类是不可以访问子类特有的方法的
Animal *an3 = [Animal new];
[(Dog*)an3 bark]; //错误的,不能强制转换

九. 实例变量修饰符

1.实例变量的作用域
  • 作用域
    • 从出现的位置开始,直到下一修饰符出现,如果没有遇到下一个实例变量的修饰符,那么就会修饰后面所有的实例变量
  • 1)@public (公开的)在有对象的前??下,任何地方都可以直接访问。
  • 2)@protected(默认) (受保护的)只能在当前类和子类的对象方法中访问
  • 3)@private (私有的)只能在当前类的对象方法中才能直接访问
  • 4)@package (框架级别的)作用域介于私有和公开之间,只要处于同一个框架中相当于@public,在框架外部相当于@private
  • 5)将成员变量/方法写到.m中,就会是完全私有化,子类看都看不到
2.变量修饰符在子类中的访问
  • 1)@private私有成员是能被继承,也不能被外部方法访问。
  • 2)@public 公有成员能被继承,也能被外部方法访问。
  • 3)@protected 保护成员能够被继承,不能够被外部方法访问。
3.实例变量作用域使用注意事项
  • (1)在@interface...@end之间声明的成员变量如果不做特别的说明,那么其默认是protected 的。
  • (2)一个类继承了另一个类,那么就拥有了父类的所有成员变量和方法,注意所有的成员变量它都拥有,只是有的它不能直接访问。例如@private的

十. description

  • 获取Person对应的类对象
Class c = [Person class];//结果是:Person
  • class注意c小写,只要给类发送class消息,就会返回当前类的类对象
1.description基本概念
  • NSLog(@"%@",objectA);

    • 只要利用%@打印某个对象,这时系统内部默认就会自动调用objectA的父类的description方法来输出ObjectA的描述信息.
  • description方法默认返回对象的描述信息(默认实现是返回类名和对象的内存地址)

2.description重写的方法
  • description方法是基类NSObject所带的方法,因为其默认实现是返回类名和对象的内存地址, 这样的话,使用NSLog输出OC对象,意义就不是很大,因为我们并不关心对象的内存地址,比较关心的是对象内部的一些成变量的值。因此,会经常重写description方法,覆盖description方法 的默认实现

  • 对象方法

/**对象方法:当使用NSLog输出该类的实例对象的时候调用*/
-(NSString *) description
{
    return [NSString stringWithFormat:@"狗腿数:%d,狗眼数%d\n",_legNum,_eyeNum];
}
 
  • 类方法
/**类方法:当使用NSLog输出该类的类对象的时候调用*/
+(NSString *) description
{
    return @"+开头的description方法";
}
  • 注意
    • 调用description方法就会返回一个字符串,字符串默认格式<类名称: 对象名称>
    • 可以重写description方法,返回我们需要打印的内容
    • 如果通过%@打印的是对象就会调用以-号开头的(对象)方法
    • 如果通过%@打印的是类对象就会调用以+号开头的(类)方法
3.description陷阱
  • 访问属性的方式

        p->_age;
        [p age];
        p.age;
        self.age
        [self age];
        self->_age;

     

  • (建议)千万不要在description方法中同时使用%@和self,下面的写法是错误的

- (NSString *)description {
    return [NSString stringWithFormat:@"%@", self];
}

 

  • 同时使用了%@和self,代表要调用self的description方法,因此最终会导致程序陷入死循环,循 环调用description方法

  • 当[NSString stringWithFormat:@“%@”, self]; 使用它时,循坏调用,导致系统会发生运行时错误。

  • 当该方法使用NSLog(“%@”,self) 时候, 系统做了相关的优化,循坏调用3次后就会自动退出

4

OC脱变第三天

标签:

原文地址:http://www.cnblogs.com/HMJ-29/p/4687345.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!