【Objective-C 篇】 ☞ 2. 属性、方法

1. 属性(Property)和实例变量(instance variable)

1.1 当定义一个属性时,本质上是在干什么(编译器在帮我们干什么):

1) 生成实例变量用来保存属性的值

2) 生成访问器(settergetter方法)用于修改和访问属性的值

1.2 实际开发中知道的事:

1) 只读属性:只能读取值,不能修改值。这种属性只生成getter方法,不生成setter方法。

2) 计算属性:没有对应的实例变量,属性的值经常是通过计算得到的。在swift,这种属性叫计算属性。

3) 自定义setter/getter:一个属性的getter方法和setter方法都可以由程序员自定义。当程序员不满意编译器生成的访问方法(setter/getter)时,可以自定义。

a.如果只自定义了setter方法,编译器补上getter方法和实例变量

b.如果只自定义了getter方法,编译器补上setter方法和实例变量

c.如果自定义了gettersetter,编译器就会认为你不需要实例变量,不会补上实例变量

1.3 属性的其他细节

1) 如果gettersetter都自定义了,实例变量就不会自动生成,但如果需要实例变量,可以使用属性合成器synthesize指定实例变量:

implementation中,加一句: @synthesize 属性名 = 实例变量名;

//使用属性合成器指定属性所对应的实例变量

@synthesize age = _age;//此时编译器会生成_age这个实例变量

2) 如果getter方法和setter方法不需要编译器生成,可以在.m文件中使用 @dynamic 来要求编译器不要生成访问方法。

应用场景:一般会在CoreData的代码使用这种方式。

@dynamic 属性名; //不要生成此属性的settergetter

特殊属性,编译器不生成settergetter,程序在运行时才通过特殊手段获得settergetter方法。

经常会在CoreData的代码中看到这种情况。(如:属性的值需要获取后台数据库读到) 

3) 实例变量的访问范围

  • 在接口部分(.h文件中)定义的实例变量默认(@protect)可以在本类的内部,及子类的内部访问。
  • .m文件中定义的实例变量,只能在本类的内部访问。其实地方都访问不了。都是私有的。
  • 在接口部分(.h文件中)定义的实例变量如果真希望别人也访问,可以用@public将其公开。我们不建议这么做。

//实例变量的访问修饰符

{

@protected //默认是保护,可省略不写

    int protectedVar;//默认是保护的,只能在本类内部及子类内部访问

@public

    int publicVar;//公开的实例变量,一般不这样做

@private

    int privateVar;//私有的实例变量,只能在本类的的内部访问

}

2. 初始化方法(构造方法)

2.1 概念

一种特殊的方法,专门用于初始化对象。

OCinit开头的方法,我们称之为初始化方法(构造方法)。

     构造方法的用途:用于初始化一个对象,让某个对象一创建出来就拥有某些属性和值

[[类型 alloc]init]; //init就是初始化方法

 

2.2 怎么写

任何一个对象,都默认有一个初始化方法:init,是从NSObject类中继承来的。

如果程序员不满意继承来的init方法,可以自己重写。

怎么写?固定写法:

1) 必须先调用父类的初始化方法,并将返回值赋值给self(self是指向当前对象的引用)

2) 如果父类初始方法调用成功,此时给对象中的属性赋初始值。初始化对象的主要目的就是给属性赋值

3) 方法结束时,必须返回当前对象(self).

注意: 初始化方法返回空代表初始化失败

    

2.3 初始化方法的注意事项

1) 初始化方法可以有多个,初始化对象时可以选择的调用。

2) 当一个类没有提供任何初始化方法时,也有init方法。从父类继承来的init方法会将所有的属性初始化为0.

3) 关于空(nil),OC中表示空指针的字面值是nil,相当于C语言中的NULL

    

4) 返回值类型instancetypeinstancetype会自动把返回值类型变成具体的类型)

  • iOS7 SDK开始, 初始化方法,以及创建对象的工厂方法,其返回值全部使用instancetype类型。
  • instancetype会自动根据方法的返回对象识别返回类型(返回什么类型的对象instancetype就变成什么类型,instancetype会自动知道返回值的类型),instancetype只能出现在返回值类型上。

2.4 id类型

id类型是动态类型,当程序运行到这句话时,才知道这句话某一个变量是什么类型。

id类型定义的变量,它里面存的这个值的类型不确定。运行时才确定,编译时也不确定。也叫万能指针。

  • id类型是万能类型,有风险;id类型只针对对象类型,不针对基本类型;id类型只能指向对象。是一种通用对象类型!
  • id类型的变量其实是一个可以指向任何类型对象的引用(指针),类似于C语言中的void*(万能指针)

如:id r = [[TRPerson alloc]init];

id类型被定义为指向NSObject子类的实例对象的指针

double d = 10.5;

id a = &d;//ERROR

id是一个指针,但在使用时无需加*

id stu = nil;

id类型的变量可以出现在变量能出现的任何地方,比如方法的参数上,返回值类型上,或直接定义局部变量等。

使用id类型的好处:可以指向任何对象; 坏处:编译器失去了对类型的检查。

 

总结:idinstancetype的区别

  1. id可以做方法的返回值类型,方法的参数类型,还可以直接声明变量,或定义成属性
  2. instancetype只能做初始化方法和工厂方法的返回值类型,不能在方法的参数等地方使用instancetype

instancetype类型比id类型好一点:因为instancetype会自动把它的返回值类型转换成它具体的类型。而id类型则是万能类型,带有一定的风险(还要做一些类型转换,多了一些步骤,性能和效率会低一点)。

3. 类方法(class method)

3.1 概念

1) 实例方法(instance method):

"-"号开头的方法叫实例方法

必须通过实例(对象)去调用,向对象发消息会调用实例方法

2) 类方法

"+"号开头的方法叫类方法

必须通过类去调用,向类发消息就会调用类方法

如果一个方法的具体实现与对象无关(即不会使用对象的属性或实例变量),就可以考虑写成类方法!!!

注意:

类方法中不能使用类的成员变量!(即在类方法中不能直接访问对象的东西)

在实例方法中可以使用类的成员变量!

 

3.2 为什么使用类方法

1) 类方法的调用比较方便,不用创建对象就可以

2) 如果有一个方法,不需要使用某个对象属性,那么可以考虑写成类方法,为了方便调用。

3) 经常使用类方法来创建对象,这种类方法被称为简单工厂方法,或直接叫工厂方法

在类方法中,不能直接访问属性和实例变量,也不能直接调用实例方法。(与对象有关的操作在类方法中都不能用!)

类方法属于整个类,和具体的对象无关,所以对象的属性和实例变量不能在类方法中访问。

    

4. 工厂方法(Factory Method)

一个类为了方便创建对象,提供一个类方法返回一个新对象,这个类方法就叫工厂方法。是简单工厂模式的具体体现。

工厂方法就是把alloc方法和init方法合并写成一个方法。

工厂方法的方法名格式:类名WithXXX…开头(类名首字母小写)

TRPoint *p1 = [[TRPoint alloc]initWithX:1 andY:2];//一般创建对象

TRPoint *p2 = [TRPoint pointWithX:2 andY:4];//用工厂方法创建对象

   

5. 单例模式(Singleton):就是单个实例的意思。是一种特殊的工厂方法。一个类只允许创建一个对象。

什么是单例模式:

1)主要用于做应用程序的资源共享控制

2)只能生成唯一的对象

3)利用类方法来创建和访问对象

单例模式的原理:

1)类中定义一个实例(static全局变量)

2)类中定义一个类方法作为单例方法

3)在单例方法中如果类中定义的实例为空,则创建该类的实例;否则返回此实例。

     

     

单例模式的好处:节约资源、提高效率、统一管理。

NSNotificationCenter 通知中心 也是一个单例类

UIApplication(代表一个应用程序,App是唯一的) 就是一个单例类

   

设计模式:(经典23种设计模式)

解决一个典型问题的最佳方案。

工厂模式: 简单工厂模式(工厂方法)   工厂模式  抽象工厂

 

简写方式:[TRPoint new];相当于写[[TRPoint alloc]init]; (一个意思的不同写法)

[[TRPoint alloc]init]这种写法方便重写初始化方法(init..)[TRPoint new]这种写法不能。

 

posted @ 2017-02-26 17:38  专注·精彩  阅读(934)  评论(0编辑  收藏  举报