Object-C基础(7)——类与对象

Object-C的面向对象

       类:一批具有相同特征的对象的统称(一批相似对象的概念)

       类:一批对象的总称。

       对象:具体存在的东西。

       定义类的语法:

               Object-C定义类,需要2个部分:

               头文件部分(声明部分)    —— 相当表盘部分,暴露出来供用户操作的。

               @interface <类名> :NSObject

      {

           成员变量

      }

      方法声明

      @end

      类名:只要是一个标识符即可。但从程序可读性的角度来看,类名必须是由一个或多个有意义的单词连缀而言。

      成员变量:用于描述该类或该类的对象所具有的状态信息。程序只记录与业务相关的状态信息。

                      语法:<类型> <变量名>; 

      方法:用于描述该类或该类的对象所具有的行为。程序只记录与业务相关的行为。

              方法语法:

        +|- (返回值类型) 方法名: (形参类型1) 形参名1 形参标签2: (形参类型2) 形参名2 形参标签3: (形参类型3) 形参名3 ...

        +表明该方法属于类本身,该方法只能由类来调用;-表明该方法属于该类的对象,因此只能由于对象调用。

                 返回值类型,可以是任意有效的类型。

              方法名,只要是一个有效的标示符即可。但从程序可读性角度来看,方法名应该是一个或多个单词连缀而言,最好方法名是动词。

              形参列表:除了第一个形参之外,后面每个形参都需要3个部分:形参标签: (形参类型) 形参名

                实现部分 —— 相当于表体部分,被彻底隐藏的,但负责提供表盘部分的显示。

              @implementation <类名>

      {

           成员变量   —— 此处定义的成员变量,相当于被隐藏的成员变量。

      }

      实现接口部分定义的所有方法。

      额外定义实现部分的方法。—— 此处额外定义的方法,相当于是被隐藏的方法,因此不能被调用。

      @end

类的作用:

      1. 定义变量。所有类,都属于指针类型。

      2. 创建对象。

      3. 调用类方法。

      4. 用于被继承、派生子类。

      【不存在的】: 可以访问类变量 ———— 但不存在。Object-C的类不能定义类变量。

创建对象

      [[类名 alloc] init]

      init,包括后面的系列initWithXxx方法,被称为初始化方法。

      [类名 new] - 很少使用。

        对象的作用:

      1. 调用实例方法

      2. 访问实例变量

         对象变量 -> 成员变量

调用方法

        [类|对象 方法:参数1 形参标签2: 参数2 形参标签3: 参数3...];

对象与指针

      用自定义类来声明变量时,都需要在类名后添加一个*,表明这是一个指针。

      指针:意味着,当程序把一个对象赋值给指针变量时,实际上只是把该对象的首地址存入指针变量,并未真正把对象存入指针中。

      同一个对象,可以被很多个指针变量(引用变量)指向(引用)它。

      反过来:供一个指针变量,最多只能指向一个对象。

      对象 —— 只是赋值,不会创建对象。要看到allocate(分配内存)才会创建对象。

      dealloc —— 删除内存,销毁该对象。

      self 关键字 代表了调用方法的调用者。通俗来说,谁调用方法,self就代表谁。

             如果在实例方法中,总是由实例调用,因此self总是代表调用该方法的对象;

             如果在类方法中,总是由类调用,因此self总是代表调用该方法的类本身。

      self,主要是作为一个代词。 当它出现在任何方法中,谁调用该方法,self就代表了谁。

      id类型

      C/Object-C都是强类型的语言,指定的类型的变量,只能接受指定类型的对象。

      但id不同,它可以接受任意类型的对象。

     对于id类型的变量而言,它可以在运行时动态解析、绑定要调用的方法。

     需要说明都是,动态绑定,必须绑定的是实际存在的方法——否则一样会编译出错。

     只有方法才会执行动态绑定,即使成员变量是id类型,成员变量也不会执行动态绑定。

     【注意:】如果程序对id类型的指针变量的成员变量进行赋值,程序会编译报错。方法详解:

     理解方法:

      1. 方法和函数的本质是一样的。

      2. 定义方法时,方法不能独立存在,必须定义在类里面。有的方法(+)属于类;有的方法(-)属于实例(对象)

      3. 调用方法时,方法也必须有调用者 —— 调用者被称为主调(主语、调用者)

         对于+方法,调用者必须是类本身。对于-方法,调用者必须是实例。

        猪八戒吃西瓜

         [猪八戒 吃:西瓜];

         猪八戒.吃(西瓜);

      形参个数可变的方法

           调用该方法时,可以为该参数传入多个值。

           声明方法时,需要使用 ,... 形式来声明个数可变的形参。

           实现方法时,需要利用如下来获取调用方法时传入的多个参数:

           va_list:这相当于一个指针类型。

           va_start: 它是一个函数。va_start(va_list类型变量 , 个数可变的形参名);

           va_arg: 它也是一个函数,每次获取一个参数值。

           va_end:处理完成后,就使用该函数来关闭va_list类型的变量。

      #import "FKComputer.h"

     @implementation FKComputer

     - (void) print: (NSString*) content , ... 
     {
	// 定义一个va_list类型的变量,用于获取程序传入的多个个数可变的参数
	va_list argList;
	
	// 如果content存在——至少content参数的第一个值要是存在的。
	if( content )
	{
		// 首先处理content参数的第一个值
		NSLog(@"%@" , content);
		// 将content参数的参数列表绑定给argList
		va_start(argList , content);
		
		// 程序每调用va_arg一次,即可获取一个参数值。
		NSString* arg = va_arg(argList , id);
		// 如果arg不为nil,就处理该参数——但如果最后一次取出的是nil,循环结束。
		while( arg )
		{
			NSLog(@"%@" , arg);
			arg = va_arg(argList , id);
		}
		
		va_end(argList); // 结束处理。
	}

     }

@end


       注意:

        1. 个数可变的形参只能作为方法的最后一个形参,因此一个方法最多只能声明一个个数可变的形参。

        2. 调用个数可变的形参的方法时,程序至少要为个数可变的形参传入一个参数。

 变量

     全局变量:在源文件范围内声明(不再任何花括号中)。

         直接保存在静态存储区的,程序退出时,全局变量才会死亡。  

         系统会为全局变量自动分配初始值。初始值为广义的0。

     局部变量:在函数或方法中声明的。

         保存当前的方法或函数栈的,因此随着方法或函数的结束而死亡。

         局部变量在程序显式赋初始值之前,局部变量的值是不确定。

     成员变量(实例变量):在类后面(接口或实现部分)的一对花括号中。

         成员变量会随着对象的allocate而分配内存,成员变量开始出现。

         随着对象被回收,成员变量才会被销毁。

         实例变量,随着实例的生而生;随着实例的死而死。

         ——在ARC机制下,如果一个对象没有任何引用变量指向它,那么该对象就会被销毁。

         系统会为成员变量自动分配初始值。初始值为广义的0(0、0.0、nil)

         实质上,创建对象时,alloc负责分配内存; init就负责执行默认的初始化。

      生命期限:

         局部变量 < 成员变量 < 全局变量

         Object-C所有的成员变量都是实例变量,因此OC只有实例变量,没有类变量。   

     模拟类变量

         用一个static全局变量可模拟类变量。

         static全局变量 —— 只能在当前源文件中被访问的全局变量,内部全局变量。

      步骤:

       (1)在类的实现部分定义一个static全局变量。

         (2)为该类声明、并实现一组getter和setter的类方法,用于操作该static全局变量

              其中getter方法用于获取全局变量的值;setter方法用于修改全局变量的值。

 封装

     面向对象的3大特征: 封装、继承、多态。

     封装:无处不在。封装包括2方面的含义:

     - 把对象的实现细节隐藏在内部。         合理隐藏。

     - 把供用户操作的interface暴露出来。    合理暴露。

     Object-C实现封装的方式:

       通过访问控制符。

                ↗   @package  ↘

       @private                     @public

                ↘  @protected ↗

      @private:彻底隐藏的访问控制符。被@private控制的成员变量,只能在当前类中被访问。     (彻底隐藏)

       @package:被@package控制的成员变量,只能在当前类和当前类的同一个映像中被访问。       (部分隐藏:在同一个映像内不隐藏)

       @protected:被@protected控制的成员变量,只能在当前类和当前类的所有子类中被访问。     (部分暴露)

       @public:被@public控制的成员变量,可以在任意地方被访问。                           (彻底暴露)

                             当前类    与当前类的同一个镜像      当前类的子类      全部范围

       @private         √                    ×                                            ×               ×

       @package      √                   √                                             ×               ×

       @protected     √                    ×                                            √               ×

       @public          √                    √                                             √               √

       如果成员变量没有使用访问控制符,默认使用@protected修饰。

       Object-C的权限控制符,是从当前权限控制符开始,一直管到下一个权限控制符。

       一般来说,设计一个类时,推荐做法是:

       (1)将成员变量使用private隐藏起来,避免程序直接访问该成员变量。

       (2)为该成员变量提供setter、getter方法,setter、getter方法就可添加控制访问逻辑,

                 从而避免直接修改对象的成员变量的值造成的破坏。

        对于方法而言,不能使用@private、@protected、@package、@public控制。

        所有在接口部分声明过的方法,都是暴露的方法(相当于public)。

        如果只在实现部分实现、未在接口部分声明的方法,都是私有方法(相当于private)。

        关于@package的理解

               1. 被@package的成员,肯定可以在当前类中被访问。

               2. 同一个镜像。 只要和当前类编译成一个文件(包括同一个可执行文件、同一个库文件等),即可称为同一个镜像。

        以后在开发APP时,可以只是简单地将成员声明为@package。

        合成getter、setter方法

            (1)用@property来声明属性。

                      @property (指示符)NSString* brand;

                     一条property定义,可以得到3个东西:

                   (1)得到一个在属性名前面添加_前缀的成员变量——这是成员变量,也是被彻底隐藏的。

                   (2)getter方法。

                   (3)setter方法。

                    如果我们认为系统实现的getter、setter方法不好,程序也可在实现部分重新实现setter、setter方法。      

               (2) 可选的。如果你希望改变@property合成属性所对应的成员变量名,才需要在实现部分使用@synthesize指令。

                   @synthesize 属性名;   ——  让合成属性对应的成员变量名与属性名完全相同。

                   @synthesize 属性名 = 新名字;   ——  让合成属性对应的成员变量名为新名字。

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值