学习目标

1.【掌握】Xcode开发文档

2.【掌握】static关键字

3.【掌握】self关键字

4.【掌握】继承

5.【掌握】NSObject

6.【掌握】访问修饰符

7.【掌握】私有实例变量和私有方法

8.【掌握】多态

9.【掌握】description

一、Xcode开发文档

苹果提供了很多的框架,每个框架中有很多类,每个类有很多方法,每个方法也有各种不同的用法。我们怎么查看这些框架里的这些类里的这些方法呢?苹果为我们提供了一个全面、丰富、牛逼的开发文档,只要我们装上就能随时查看了。


安装和查看文档

在线安装:Xcode -> Preferences -> Downloads ->
Documentation,选中需要下载的直接下载,国内下载非常慢。(不推荐)

离线安装:网上下载离线包,复制到文档路径:

/Applications/Xcode.app/Contents/Developer/Documentation/DocSets里。(推荐)

查看文档:Window -> Documentation and API Reference 里可查看。

二、static关键字

static关键字在OC中也能使用,但是不能修饰属性也不能修饰方法。但可以修饰方法内部的局部变量,被static修饰的局部变量是静态变量,存储在常量区,当方法执行完毕之后,局部变量不会被回收。下次再声明的时候不会再重新声明一次,二是直接使用。

使用场景:当我们需要每次创建学生时就为学生自动赋值学号

Student.h文件

#import

@interface Student : NSObject
{
    //学号
    int _studyId;
}
//_studyId的get方法声明
- (int)studyId;

//实例化一个对象的类方法声明
+ (Student *)student;
@end

Student.m文件

#import "Student.h"

@implementation Student
//_studyId的get方法实现
- (int)studyId{
    return _studyId;
}

//实例化一个对象的类方法实现
+ (Student *)student{
   
//将局部变量用static关键字修饰为静态变量
    static int studyIdTemp =
1;
    
    //实例化一个对象student
    Student *student =
[Student new];
    
   
//为student对象的_studyId实例变量赋值局部变量studyIdTemp
    student->_studyId =
studyIdTemp;
    
   
//每次调用这个类方法实例化一个对象,studyIdTemp自增1
    studyIdTemp++;
    
    //返回student对象给调用者
    return student;
}
@end

main.m文件

#import
#import "Student.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
     
  //调用Student的类方法实例化3个对象,会在类方法实现内部自动为学号赋值
     
  Student *student1 = [Student student];
     
  Student *student2 = [Student student];
     
  Student *student3 = [Student student];
     
  NSLog(@"他们的学号分别为student1 = %i student2 = %i
student3 = %i",[student1 studyId],[student2 studyId],[student3
studyId]);
     
  //输出 他们的学号分别为student1 = 1 student2 = 2 student3
= 3
    }
    return 0;
}

从上面例子不难得出,当我们希望一个方法内部的局部变量能被多次调用,在方法执行完毕后不被销毁,这个时候我们就可以使用static来修饰我们的局部变量。

三、self关键字


self与对象方法

在方法的实现内,是可以声明一个和实例变量同名的局部变量,此时局部变量会屏蔽掉同名的实例变量的作用域(在局部变量的作用域范围内屏蔽掉实例变量的作用域)。但是我们可以使用self来访问被屏蔽作用域的实例变量,这个时候self指针指向当前对象(谁调用就指向谁)。(PS:我也不知道这样形容严谨不,就是这个意思哈,你懂就行)

如果方法中有一个局部变量和实例变量同名,要访问实例变量必须使用self,不过我们在开发中一定不要在方法实现内声明和实例变量同名的变量。

应用案例:

Person.h文件

#import
@interface Person : NSObject
{
    NSString *_name;
    int _age;
}
//_name的set和get方法声明
- (void)setName:(NSString *)name;
- (NSString *)name;
//_age的set和get方法声明
- (void)setAge:(int)age;
- (int)age;
@end

Person.m文件

#import "Person.h"
@implementation Person
//_name的set和get方法实现
- (void)setName:(NSString *)name{
    NSString *_name =
@"同名变量";
    self->_name =
name;//这里就是将传入的值赋值给当前对象的实例变量_name
}
- (NSString *)name{
    return _name;
}
//_age的set和get方法实现
- (void)setAge:(int)age{
    int _age = 18;
    _age =
age;//这里不使用self则是赋值给局部变量_age
}
- (int)age{
    return _age;
}
@end

main.m文件

#import
#import "Person.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
     
  //实例化一个p对象,并调用set方法赋值
     
  Person *p = [Person new];
     
  [p setName:@"周剑峰"];
     
  [p setAge:20];
     
  
     
  NSLog(@"name = %@ age = %i",[p name],[p
age]);
     
  //打印出 name = 周剑峰 age = 18
     
  //而不是 name = 周剑峰 age = 20
    }
    return 0;
}


self与类方法

self也可以在类方法中使用,这个时候self指针指向当前类。所以我们就能通过self来调用其他类方法,并且强烈推荐使用这种方式来调用其他类方法,而不是通过类名来调用。

应用案例:

Person.h文件

#import
@interface Person : NSObject
//声明两个类方法
+ (void)sayHi;
+ (void)sayHello;
@end

Person.m文件

#import "Person.h"
@implementation Person
//在类方法实现里调用另一个类方法
+ (void)sayHi{
   
NSLog(@"类方法sayHi");
    [self
sayHello];//建议使用self调用
    [Person
sayHello];//不建议使用类名调用
}
+ (void)sayHello{
   
NSLog(@"类方法sayHello");
}
@end

main.m文件

#import
#import "Person.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
     
  [Person sayHi];
     
 
    }
    return 0;
}

四、继承


当多个类具有相同成员的时候,那么这个时候就可以把相同的成员抽取出来定义到一个类中,让其他类继承这个类。当建立了继承关系,子类(派生类)就拥有父类(基类)所有成员,并且子类可以重写父类方法也能新增子类特有的方法和实例变量。

语法:@interface
子类类名 : 父类类名

Person.h文件

#import

//性别枚举
typedef enum {
    GenderMale,
    GenderFemale
}Gender;

@interface Person : NSObject
{
    NSString *_name;
    Gender _gender;
    int _age;
}

//_name的set、get方法声明
- (void)setName:(NSString *)name;
- (NSString *)name;

//_gender的set、get方法声明
- (void)setGender:(Gender)gender;
- (Gender)gender;

//_age的set、get方法声明
- (void)setAge:(int)age;
- (int)age;

//父类吃食物方法声明
- (void)eatWithFoodName:(NSString *)foodName;
@end

Person.m文件

#import "Person.h"

@implementation Person

//_name的set、get方法实现
- (void)setName:(NSString *)name{
    _name = name;
}
- (NSString *)name{
    return _name;
}

//_gender的set、get方法实现
- (void)setGender:(Gender)gender{
    _gender = gender;
}
- (Gender)gender{
    return _gender;
}

//_age的set、get方法实现
- (void)setAge:(int)age{
    _age = age;
}
- (int)age{
    return _age;
}

//父类吃食物方法实现
- (void)eatWithFoodName:(NSString *)foodName{
   
NSLog(@"%@吃%@",self->_name,foodName);
}
@end

Student.h文件

//导入Person类的头文件
#import "Person.h"

//Student类继承Person类
@interface Student : Person
{
    int _studyId;
}

//Student类特有实例变量的set、get方法声明
- (void)setStudyId:(int)studyId;
- (int)studyId;

//Student类特有学习方法
- (void)study;
@end

Student.m文件

#import "Student.h"

@implementation Student

//Student类特有实例变量的set、get方法实现
- (void)setStudyId:(int)studyId{
    _studyId =
studyId;
}
- (int)studyId{
    return _studyId;
}

//Student类特有学习方法
- (void)study{
   
NSLog(@"学生类特有的学习方法");
}
@end

main.m文件

#import
#import "Student.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
     
  Student *stu = [Student new];
     
  
     
  //继承父类的实例变量
     
  [stu setName:@"周剑峰"];
     
  [stu setGender:GenderFemale];
     
  [stu setAge:20];
     
  
     
  //学生类的特有实例变量
     
  [stu setStudyId:2];
     
  
     
  //输出学生的信息
     
  NSLog(@"name = %@ gender = %d age = %i studyId =
%i",[stu name],[stu gender],[stu age],[stu studyId]);
     
  
     
  //继承父类的方法
     
  [stu eatWithFoodName:@"米饭"];
     
  
     
  //子类特有的方法
     
  [stu study];
     
  
    }
    return 0;
}


注意:

1.构成继承关系的类,他们直接应该有所属关系。比如学生是一个人(学生类继承人类),狗是一个动物(狗是一个动物)。

2.从父类继承的方法,不适用于子类时,可以直接声明父类的同名方法,并定义(这就是重写方法)。

3.子类重写方法之后,在调用方法时,父类的对象调用父类的方法,子类的对象调用子类的方法,不会引起冲突。

4.子类重写方法之后,子类可以通过super关键字调用父类的类方法(这里的super也相当于一个指向父类的指针)。

5.只要某个成员不是所有子类都拥有的,那么这个成员就不应该定义在父类中。

6.一个类只能有一个父类,objective-c不支持多继承。

7.子类和父类中不能有同名的属性。

8.super关键字用在子类对象方法中,可以调用当前子类继承的父类的对象方法。

9.super关键字用在子类的类方法中,可以调用父类的类方法。

继承的特点

1.单根性:一个类只能有一个父类,objective-c不支持多继承。

2.传递性:当A类继承B类,B类又继承自C类。B类继承了C类所有成员,A类又继承了B类所有成员(包括B类继承的C类所有成员)。

五、NSObject

要实例化一个对象,必须要调用这个类的类方法new,而这个方法定义在NSObject之中。所以,为了保证我们的类拥有创建对象的能力,那么我们的类必须直接或间接的从NSObject类继承。

NSObject类是所有类的基类,在这个类中定义了一个实例变量isa指针,指向代码区中类的地址。

六、访问修饰符

访问修饰符是用来修饰类的实例变量的,被不同访问修饰符修饰的实例变量的访问权限是不同的。所以,访问修饰符的作用就是用来限制实例变量的访问权限的。

@public 共有的

被@public关键字修饰的实例变量可以通过对象名在任意的地方访问。


@protected 受保护的

被@protected关键字修饰的实例变量只能在本类和他的子类访问。如果实例变量没有被访问修饰符修饰,默认修饰符就是@protected。


@private 私有的

被@private关键字修饰的实例变量只能在本类的内部访问,子类能继承私有成员,但在子类方法实现中无法访问继承的私有成员。


@package 包权限

被@package关键字修饰的实例变量只能在当前框架中访问。

七、私有实例变量和私有方法


私有实例变量

将实例变量定义在@implementation中,这些实例变量就是私有实例变量,这些私有实例变量只能在本类中访问,不能在其他地方访问,并且Xcode都不提示类中存在的私有实例变量。注意:这种情况可以在子类中定义和父类私有实例变量同名的实例变量。

@implementation Person

{

NSString *_name;

//定义在这里的实例变量只能在本类中访问

}

@end


私有方法

没有方法的声明,只有方法的实现。这样的方法就只能在类的内部调用。

八、多态

多态就是父类指针指向子类对象

1.当方法的参数是一个父类类型的时候,那么传递的实参可以是父类对象也可以是子类对象。

2.当一个父类指针指向一个子类对象的时候,只能通过父类指针访问子类对象中的继承成员,子类独有的不能访问。


多态的好处

多态的主要好处就是简化了编程接口。它容许在类和类之间重用一些习惯性的命名,而不用为每一个新加的函数命名一个新名字。这样,编程接口就是一些抽象的行为的集合,从而和实现接口的类的区分开来。

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

九、description

%@是专门用来输出对象的,默认情况下,我们将对象以%@的格式输出,输出的是

<对象所属的类名:对象的地址>

NSLog(@"%@",对象名);输出一个对象的时候,会先调用传入对象的description方法,这个方法的返回值是字符串(NSString
*),然后将这个字符串输出。我们可以重写description方法,输出我们需要输出的任意内容。

- (NSString *)description{

NSString *str =
@"<<重写了description方法>>";

return str;

}

这个时候我们在使用NSLog(@"%@",对象名);输出的是

<<重写了description方法>>

温馨提示:欢迎分享本文,转载请保留出处!

018-继承-OC笔记的更多相关文章

  1. 【09-23】js原型继承学习笔记

    js原型继承学习笔记 function funcA(){ this.a="prototype a"; } var b=new funcA(); b.a="object a ...

  2. 【转载】Javascript原型继承-学习笔记

    阮一峰这篇文章写的很好 http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javas ...

  3. OC笔记一:Objective-C简介

    1.OC简介 全称:Objective-C,是扩充C的面向对象编程语言,主要用于iOS和Mac OS开发. C语言的基础上,增加了一层最小的面向对象语法 完全兼容C语言 可以在OC代码中混入C语言代码 ...

  4. [OC笔记] Category分类之见解

    用过别的语言做过开发的同学都知道,如果你想扩充一个类,就应该去继承这个类.但是OC里面有更好的方法,那就是分类. 那什么是分类呢?就是在不改变原先类,我们可以在其中添加咱们自定义的方法,这样和同事合作 ...

  5. Joinpoint继承体系-笔记

    Joinpoint继承层次图: 由上图可以知道的所有的接口的实现都在ReflectiveMethodInvocation这个类中.ConstructorInvocation接口只有一个方法,这个方法的 ...

  6. OC笔记一:Objective

    1.OC简介 全称:Objective-C,是扩充C的面向对象编程语言,主要用于iOS和Mac OS开发. C语言的基础上,增加了一层最小的面向对象语法 完全兼容C语言 可以在OC代码中混入C语言代码 ...

  7. JavaScript 类型、原型与继承学习笔记

    目录 一.概览 二.数据类型 1. JavaScript中的数据类型 2. 什么是基本类型(Primitive Data Type) 2.1 概念 2.2 七个基本类型 2.3 基本类型封装对象 3. ...

  8. [OC笔记] protocol之我的见解

    OC中的protocol就是和JAVA中interface差不多的东西,但是又不是完全一样的.这个protocol常用来实现委托,也就是自己不实现,当事件产生的时候去回调委托者. 让委托者去执行响应的 ...

  9. [OC笔记]@property之个人理解,大神轻拍

    /** * 一个简单的对象 * * @author suzhen * */ public class SimpleObjcet { /** * 声明一个age字段 */ private Object ...

随机推荐

  1. Docker 移除镜像

    如果要移除本地的镜像,可以使用 docker rmi 命令.注意 docker rm 命令是移除容器. $ sudo docker rmi training/sinatra Untagged: tra ...

  2. Android Multimedia框架总结(二十一)MediaCodec中创建到start过程(到jni部分)

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/53386117 我最近正在参加CS ...

  3. Python 3 智能发音

    真是十分神奇.. import win32com.client import time s = win32com.client.Dispatch("SAPI.SpVoice") s ...

  4. Python尾递归-创始人为何不愿TRE以及我们如何模拟TRE

    TRE=Tail Recursion Elimination 创始人是不愿意实现TRE的.他专门用了一篇文章来阐述原因. http://neopythonic.blogspot.com/2009/04 ...

  5. 【SSH系列】-- hibernate基本原理&&入门demo

        什么是hibernate?      hibernate在英文中是冬眠的意思,当冬季来临,世界万物开始准备冬眠,但是程序猿这种动物好像不冬眠,因为需求变了,要改bug,冬眠,对于对象来说就是持 ...

  6. android面试手册

    1. Android dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念 DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚 ...

  7. 乐观的并发策略——基于CAS的自旋

    悲观者与乐观者的做事方式完全不一样,悲观者的人生观是一件事情我必须要百分之百完全控制才会去做,否则就认为这件事情一定会出问题:而乐观者的人生观则相反,凡事不管最终结果如何,他都会先尝试去做,大不了最后 ...

  8. linuxsvn源代码版本库建立

    linuxsvn源代码版本库建立 下面就要建立代码的版本库做描述: 1.     安装svn版本服务器端 yum install subversion 从镜像下载安装svn服务器端,我们服务器已经安装 ...

  9. Java学习之二维数组定义与内存分配详解

    二维数组:就是元素为一维数组的一个数组. 格式1: 数据类型[][] 数组名 = new 数据类型[m][n]; m:表示这个二维数组有多少个一维数组. n:表示每一个一维数组的元素有多少个. 注意: ...

  10. CentOS下将php和mysql命令加入到环境变量中的几种方法

    Linux CentOS配置LAPM环境时,为了方便,将php和mysql命令加到系统环境命令,下面我们记录几种在linux下将php和mysql加入到环境变量中的方法. 如果在没有添加到环境变量之前 ...