[email protected]、self及类的本质

让代码书写更加简便

--1-- 设置器和访问器
1.1 setter
1.2 getter
--2-- 类的本质
2.1 类类型的对象
2.2 类的本质
2.3 如何获取类对象
2.4 类对象的使用
2.5 类对象的存储
--3-- SEL类型
3.1 SEL
--4-- @property关键字
4.1 基本概念
4.2 @property用法
4.3 @property使用注意事项
--5-- @synthesize关键字
5.1 @synthesize用法
5.2 @synthesize使用注意
5.3 @synthesize指定实例变量赋值
--6-- self关键字
6.1 介绍
6.2 在对象方法中使用self
6.3 用在类方法中使用self

【写在开头】

『在面向对象的编程中,封装是其一个重要的特性。封装将一个可供外部使用的接口暴露出来,隐藏了复杂的代码逻辑实现。

不可被外部任意存储是面向对象设计的本质,降低了数据被无用的可能性。

外部就可以通过设置器setter和访问器getter来对对象的属性进行设置和访问,而不是直接访问对象的属性->

在开发过程中,考虑到安全性要求,一般不再成员变量名前面使用@public、@protected等关键字修饰,而是使用Set方法来为对象提供成员变量的值,在set方法的内部也可以对一些不合理的赋值进行筛选过滤。』

--1-- 设置器和访问器

1.1 setter

setter方法(设置器):在set方法的内部可以对一些不合理的数据过滤筛选。set方法作用:为提供一个设置成员变量值的方法。

命名规范:

1)方法名必须以set开头

2)set后面跟上成员变量的名称,首字母大写

3)返回值一定是void

4)一定要接受一个参数,而且参数类型需要和成员变量的类型一致

5)形参名不能和变量名一样(成员变量名以_线开头,苹果官方推荐成员变量名前加_以示区分)

好处:

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

  2)对设置的数据进行过滤

{
    //成员属性
    NSString *_name;
    int _age;
}

setter

//setter
- (void)setName:(NSString *)name;
- (void)setAage:(int)age;

1.2 getter

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

命名规范:

1)一定有返回值,返回值的类型和成员变量的类型一致

2)方法名和去掉下划线的成员变量名一样(此处与Java等语言不一样)

3)不需要接收任何参数

//getter
- (NSString *)name;
- (int)age;

--2-- 类的本质

2.1 类类型的对象

类的本质其实也是对象,只不过是class类型的对象,也叫做类对象

2.2 类对象

类对象

* 类对象在程序运行时一直存在

* 类对象是一种数据结构,存储类的基本信息:类大小,类名,类的版本以及消息与函数的映射表等

* 类对象所保存的信息是在程序编译时确定,在第一次使用该类的时候被加载到内存中

* 类对象代表类,class代表类对象,类方法属于类对象

* 如果消息的接收者是类名,则类名代表类对象

* 运行时,所有类的实例都由类对象生成,类对象会把实例的isa的值修改成自己的地址,每个实例的isa都指向该实例的类对象

* 从类对象里可以知道父类的信息、可以响应的方法等

* 类对象只能使用类方法,不能使用实例方法

2.3 如何获取类对象

1)通过实例对象获取

    Person *person = [[Person alloc] init]; //创建对象

    //通过实例对象获取类对象Dog
    Class c1 = [person class]; //Class类型的是一个结构体指针
    Class c2 = [person class];

    NSLog(@"c1->%p", c1); //0x1000011d8
    NSLog(@"c2->%p", c2); //0x1000011d8

2)通过类名获取(类名其实就是类对象)

    //通过类名获取类对象
    Class c3 = [Person class];

    NSLog(@"c3->%p", c3); //0x1000011d8

发现通过类名和实例获取对象,所获得的对象是同一个

实际上,都是获得了类对象Person class

2.4 类对象的使用

1)用类对象创建对象

两个测试方法:

//对象方法
- (void)test;

//类方法
+ (void)test;

使用

    //用类对象来创建对象
    Person *person2 = [[c1 alloc] init];
    [person2 test]; //调用对象方法的test -test

2)用类对象来调用类方法

    //用类对象来调用类方法
    [c1 test]; //调用类方法 +test

2.5 类对象的存储

isa指针

  • 每一个对象都包含一个isa指针.这个指针指向当前对象所属的类。
  • [p eat];表示给p所指向的对象发送一条eat消息,调用对象的eat方法,此时对象会顺着内部的isa指针找到存 储于类中的方法,执行。
  • isa是对象中的隐藏指针,指向创建这个对象的类。
  • 通过isa指针我们可以在运行的时候知道当前对象是属于那个Class(类)的。

--3-- SEL类型

3.1 SEL

SEL:全称selector,表示方法的存储位置

方法调用的原理:其实每个类加载到内存中对象的方法都会封装成一系列的SEL列表,SEL会保存着这个方法的信息(当然包括方法的内存地址),当要调用该方法的时候,对象会通过isa指针找到内存中对应的方法的内存地址然后再调用该方法,在找到该方法之后该类对象会把该SEL放入缓存中,以便第二次寻找的时候提高效率

Person *p = [[Person alloc] init];

[p test];

寻找方法的过程

1)首先把test这个方法名包装成SEL类型的数据

2)根据SEL数据找到对应的方法地址

3)根据方法地址调用相应的方法

4)注意:在这个操作过程中有缓存,第一次找的时候是一个一个的找,非常耗性能,之后再用到的时候就直接使用了

--4-- @property关键字

4.1 基本概念

@property是编译器的指令。(编译器指令是由编译器完成的)

好处是免去我们手工书写成员属性getter和setter方法繁琐的代码。

4.2 @property用法

格式:

  @property  类型名  方法名

如:

  @property  int  age;

相当于完成了age属性的set和get方法的声明和实现

- (void)setAge:(int)age;

- (void)age;

注意:

1、在Xcode4.4之前,用于帮我们实现get/set方法的声明

2、在Xcode4.4之后,有增强功能,连实现也自动完成了

Person.h->

/*
  省略了方法的声明
  相当于是替换了下面的这两句声明
  - (void)setAge:(int)age;
  - (int)age;

 同时,还自动生成了对应的成员属性 _age,但是这个属性是私有的,外部只能通过setter/getter访问
  */
@property int age;

Person类中没有自定义 _age属性,但是@property自动生成了该属性:

@implementation Person
//对象方法
- (void)test{
    NSLog(@"-TEST");
    self->_age = 3; //在这里可以看到,@property生成了一个_age属性
}

//类方法
+ (void)test{
    NSLog(@"+TEST");
}
@end

调用:

Person *person = [[Person alloc] init]; //创建对象

//此处 _age属性由@property生成
person.age = 3; //设置成员属性
NSLog(@"person.age->%d", person.age); //3

4.3 @property使用注意事项

在老式的代码中

@property只能写在@interface [email protected]之间

@property用来自动生成成员变量get/set方法的声明(Xcode4.4之前)

告诉@property要生成的get/set方法声明的成员变量类型是声明

告诉@property要生成的get/set方法是哪个属性的,属性名去掉下划线

--5-- @synthesize关键字

5.1 @synthesize用法

@synthesize age;

写在.m文件中,表示对生成.h中变量age的get和set方法的实现

格式:

  @synthesize  方法名

注意:

如果使用@synthesize则变量名要先在.h文件中声明

.h

@property int age;

.m

@synthesize age;

展开形式如下:

@synthesize age;
//展开
- (void)setAge:(int)age{
    self->age = age; //注意这里不是对Person原来的成员变量_age赋值,而是生成了一个变量age,然后对其进行赋值
//(如果这里写self,那么这个变量age也就相当于是个成员变量了)

    //所以使用@synthesize时,下面只打印了age和name的值,没有对_age和_name进行操作
    //NSLog(@"age = %d, name = %@", age, name);
    //NSLog(@"_age = %d, _name = %@", _age, _name);
 }

5.2 @synthesize使用注意

Xcode4.4之前@property和@synthesize搭配使用,用于简化set和get方法的定义和实现

5.3 @synthesize指定实例变量赋值

声明

@property  int  a;

实现

@sythesize  a  =  _b;   //表示用a的get和set方法,修改属性b的值

相当于下面的代码:

   - (void) setA:(int)a{

  _b = a;

  }

   - (int)a{

  reurn _b;

  }

@interface Person : NSObject

@property NSString *name;
//如果两个实例变量的类型一致,如:age和weight,@property可以用逗号隔开变量,在一行上定义
@property int age, weight; 

//测试方法
- (void)test;
@end

@implementation Person

//用age的getter和setter方法,修改属性_age的值
@synthesize age = _age, name = _name, weight = _weight;
@end

--6-- self关键字

6.1 介绍

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

学会使用self,首先要搞清楚属性这一概念。

以及理解getter(访问器)和setter(设置器)方法,它到底有什么用?

设置器与访问器,提供外界操作 类内部属性的一个通道。

假如,没有这个方法,外界怎么操作类的内部属性。

假如不提供这两个方法,那么这个属性的值,就不能为外界所改变。

因为类的属性,默认是@protect(受保护类型)。

self的应用场景

1)用在类方法中

2)用在对象方法中

3)访问成员变量

4)self在OC的内存管理特殊使用

6.2 在对象方法中使用self

//学生学习对象方法
- (void)study{

    //此时self指代学生对象
    NSLog(@"- self->%p", self); //0x1002001b0
}

6.3 用在类方法中使用self

//学生信息类方法
+ (void)info{

    //此时self指代学生类
    NSLog(@"+ self->%p", self); //0x1000013d0
}

查看:

    @autoreleasepool {

        Student *stu = [[Student alloc] init];

        //学生对象地址
        NSLog(@"stu->%p", stu); //0x1002001b0

        //学生类地址
        NSLog(@"Student-%p", [Student class]); //0x1000013d0

        //发送study和info消息
        [Student info]; //0x1000013d0
        [stu study]; //0x1002001b0
    }

输出-->

综上总结:

self要指代谁?具体是要看self写在哪个方法中,

如果self写在对象方法中,则指代的就是当前方法的对象([类 new])

如果self写在类方法中,那么它指代的就是当前的类对象(类 class)

注意这里类对象和对象是两个概念

【写在结尾:】

『想起一首席慕容的诗:

一棵开花的树

如何让你遇见我
在我最美丽的时刻

为这
我已在佛前求了五百年
求佛让我们结一段尘缘
佛於是把我化做一棵树
长在你必经的路旁

阳光下
慎重地开满了花
朵朵都是我前世的盼望

当你走近
请你细听
那颤抖的叶
是我等待的热情

而当你终於无视地走过
在你身後落了一地的
朋友啊
那不是花瓣
那是我凋零的心』
时间: 2024-10-08 19:02:32

[email protected]、self及类的本质的相关文章

iOS开发核心语言Objetive C —— 编译器指令@[email protected]自定义构造方法及类工厂

本分享是面向有意向从事iOS开发的伙伴们,或者已经从事了iOS的开发者.如果您对iOS开发有极高的兴趣,可以与我一起探讨iOS开发,一起学习,共同进步.如果您是零基础,建议您先翻阅我之前分享的iOS开发分分钟搞定C语言系列,然后在开始Objective C语言的学习,如果您遇到问题也可以与我探讨,另外将无偿分享自己整理的大概400G iOS学习视频及学习资料,都是干货哦!可以新浪微博私信?关注极客James,期待与您的共同学习和探讨!!由于时间有限,每天在工作之余整理的学习分享,难免有不足之处,

iOS开发之oc(十)--类的本质、description、SEL

(一)类的本质 1.类也是个对象 其实类也是一个对象,是Class类型,简称“类对象”. // Class类型的定义 typedef struct objc_class *Class; // 类名就代表着类对象,每个类只有一个类对象 2.+load和+initialize +load >  在程序启动的时候会加载所有的类和分类,并调用所有类和分类的+load方法 >先加载父类,再加载子类:也就是先调用父类的+load,再调用子类的+load >先加载元原始类,再加载分类 >不管程序

黑马程序员— OC核心语法之构造方法、Category分类、类的本质、description和SEL

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 上一章我们学习了OC的一些核心语法,初步了解了OC作为一门开发语言的一些较为深层次的知识.本章我们继续学习OC的核心语法,主要包括OC的构造方法,Category分类,类的本质及深入研究,以及description关键字和SEL关键字. 第一讲     构造方法 1. 构造方法 构造方法是用来初始化对象的方法,是一个对象方法,以减号"-"开头,构造方法其实就是init方法,初始化完毕

OC基础[email protected]后的修饰符及其用法小结

[email protected]后的修饰符 strong : 该属性值对应 __strong 关键字,即该属性所声明的变量将成为对象的持有者,等同于"retain" weak : 该属性对应 __weak 关键字,与 __weak 定义的变量一致,该属性所声明的变量将没有对象的所有权,并且当对象被释放之后,对象将被自动赋值nil,记住IBOutlet应该使用weakcopy : 和之前的copy一样,复制一个对象并创建strong关联assign : 对象不能使用assign,但原始

[email protected] 注解原理与使用

Java反射 java反射机制的定义: 在运行转态时(动态的)时. 对于任意一个类,都能够知道这个类的所有属性和方法 对于任意一个对象,都能够知道调用它的任意属性和方法 Class对象 java中用对象来对现实生活中的事物进行抽象,如人(现实生活)抽象到一个person类(java对象).但有没有想过,java中的类(现实生活)其实也是一个Class对象(对象).因此,这个Class类就包含了所有你定义的Class信息,包括所有的方法(私有,公有).构造器.实现了那些方法.哪些注解信息.所有的属

[email protected]动态代理-类加载器

一.测试单元     概述:用于测试JAVA代码的工具类,已内置在Eclipse中;     格式:         1.在方法的上面添加@Test;         2.对被测试的方法的要求:权限-public;返回值-void;参数-空参         [email protected]:在@Test标注的方法前执行,可以用于初始化;           @After:在@Test标注的方法后执行,可以用于释放资源; 二.注解     概述:java的一种数据类型,和类/接口在同一级别  

Spring4 In [email protected]单例、多例Bean

Spring In [email protected]单例.多例Bean 代码下载地址:http://download.csdn.net/download/poiuy1991719/9967494 Singleton:单例    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)@Scope("singleton") Prototype:每次注入都会创建新的   @Scope(ConfigurableBeanFactory.SCOPE_PRO

[email protected]&@classmethod&property的理解

#!/usr/bin/evn python #_*_coding:utf8_*_ class myClass(object): age = 30 def __init__(self,name): self.name = name def sayhi1(self):#只可实例中调用 print("sayhi1...name:{}.age:{}".format(self.name,self.age)) @staticmethod #静态方法不可访问构造方法中的变量,可在实例中调用,也可类中

[email protected]:php

curl 获取页面信息 function curl_get_content($url){ $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查 curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Linux x86_64) App