iOS基础之Objective-C(四)

1、实例变量修饰符

(1)、public:可以在本类中被访问到,也可以在其他类中被访问到,当然,在子类中也能被访问到;
(2)、private:可以在本类中被访问到,但是不可以在其他类中被访问到,在子类中也同样不可以被访问到;
(3)、protected:可以在本类中被访问到,但是不可以在其他类中被访问,然而在子类中却是可以被访问到,没有写明修饰符的默认情况下的实例变量都是用protected修饰的
(4)、package:介于public和private之间
如果是在当前所在包以外,则是private,其在子类中是不可以被访问的;
如果是在当前所在包以内,则是public,其在子类中是可以被访问的。
**
不管是用什么修饰符修饰的,我们都可以在其他类中查看这个类的属性,但是有些修饰符修饰的属性我们是不能操作的,但是,在**

@implement{
//定义属性,修饰符任意
}
@end

**这个属性也是私有属性,但是这个在外界是看不到的,而private定义的属性可以看到,例:
**

//情形一
Person:NSObject{
@private
  int _age;
}
Person *p = [Person new];
p->age; //这里只有warning

//情形二
@implementation Person{
  int _age;
}
Person *p = [Person new];
p->age; //这里会报错

//情形三
@implementation Person{
@public 
  int _age;
}
Person *p = [Person new];
p->age; //这里还是会报错

2、私有“方法”与公有“方法”(OC中只有消息,没有方法)

如果只有方法的实现,没有方法的声明,那么这个方法就是私有方法,但是OC没有真正意义上的私有方法:

@implementation Person{
  int _age;
}
-(void)test {
  NSLog(@"age = %@",_age);
}
@end

//其他类里面
Person p = [Person new];
[p test];  //报错,访问不到test

id p = [Person new];
[p test];  //这里会打印->age = 0;

//或者
Person p = [Person new];
[p performSelector:@selector(test)];//这里也会打印->age = 0;

3、@property与@synthesize

(1)、@property是一个编译器指令,使用它我们可以代替setter和getter方法的声明,因此我们可以省去自己编写setter和getter方法声明;
(2)、@synthesize也是编译器指令,用来生成setter与getter方法的实现

*PS:
a、后期的@property已经同时具有声明和实现setter和getter方法的功能,如果有 @property int num; 那么他会自动找到以 _ 开头同名的
成员变量进行赋值,即:@property int num;等价于 @property int num = _num;
b、如果我们自己重写了setter与getter方法,那么编译器不会自动帮我们生成这两个方法;
c、我们可以不写成员变量的声明,并且我们没有同时重写setter和getter方法(可以重写其中一个),如方法一所示,系统会自动为我们生成一个带 _ 的成员变量,但是它是一个私有变量,只能在本类中使用;
**

下面三个写法是等价的:

//写法一
@interface Person
@property int age;
@end

@implementation Person
@end

//写法二
@interfae Person{
  int _age;
}
-(void)setAge:(int)age;
-(int)age;
@end

@implementation Person
-(void)setAge:(int)age {
  _age = age;
}
-(int)getAge{
  return _age;
}
@end

//写法三
@interface Person{
  int _age;
}
@property int age;
@end

@implementation Person
@synthesize age = _age;  //这句不能写在@interface里面
@end

注意
如果不是按照标准写法,@synthesize property = _property;的写法,而是@synthesize property;那么生成的setter与getter方法会是如下:

@interface Person{
  int _age;  //a
  int age;  //b
}
@property int age;
@end

@implementation Person
@synthesize age; 
/*
等价于
-(void)setAge:(int)age {
  age(b行的age)= age(形参age);  //而非_age = age;
}
-(int)age{
  return age;//而非return _age;
 }
*/
@end

4、description方法:

description方法是系统自带的方法,用来打印一个类或者一个对象的所有成员变量的信息,但是我们可以重写这个方法,来输出我们需要的内容。

Person *p = [Person new];
NSLog(@"%@",p);  //自动调用系统内的-(NSString *)description; 方法

Class *c = [p class];
NSLog(@"%@",c);//自动调用系统内的+(NSString *)description; 方法

综上,打印对象自动调用对象方法,打印类会调用类方法。

注意:在重写对象description方法的时候,不能用%@输出self,否则会造成死循环。

-(NSString *)description {
  NSLog(@"%@",self);    //死循环,这里输出会调用description方法
  return [NSString stringWithFormat:@"%@",self];//同理这里也会造成死循环
}

5、new与alloc和init

Person *p = [Person new];
做了三件事:
a、开辟存储空间
b、初始化所有的属性(成员变量)
c、返回对象的地址

Person *p = [Person alloc];
做了三件事:
a、开辟存储空间
b、将所有属性设置为0
c、返回当前对象的地址

Person *p2 = [p init];
做的事:
a、初始化成员变量,一般默认情况下的实现是什么都不做
b、返回初始化对象的地址

**PS:alloc返回的地址和init返回的地址是同一个地址 **


6、id与instancetype

(一)相同点:
都是万能指针,一般在多态中使用
(二)不同点:
a、id可以作为返回值,作为形参,定义变量,而instancetype只能用来作为返回值;
b、当将一个类型赋值给一个其他的类型时,instancetype能在编译时判断出其实际类型,从而给出警告,而id不会
例:

//构造方法一
- (id)init {
  if(self = [super init]) {
    _age = 10;
  }
}

//构造方法二
- (instancetype)init {
  if(self = [super init]) {
    _age = 10;
  }
}

NSString *str = [[Person alloc] init];
NSInteger len = [str length];
NSLog("%@",len);

使用构造方法一时,编译过程不会报错,但是使用构造方法二会报错,而当运行时,两者都会奔溃,因为Person类里面根本没有length方法。


7、类工厂方法

类工厂方法:用于快速创建对象的类方法,我们称之为类工厂方法。
用途:主要用于给对象分配存储空间以及初始化这个存储空间。
规范:
a、一定是类方法
b、方法名称以类的名称开头,首字母小写
c、一定有返回值,返回值是id或者instancetype
例:

+(instancetype)person {
  Person *p = [Person alloc];
  Person *p1 = [p init];
  return p1;
}

int main(){
  Person *p1 = [[Person alloc] init];  //普通方法
  Person *p2 = [Person person];  //类工厂方法
}

PS:自定义类工厂方法是苹果的一个规范,一般情况下,我们会给一个类提供自定义构造方法和自定义类工厂方法用于创建一个对象。

8、类工厂方法的继承

@interface Person :NSobject
@end
@implementation
+ (instancetype)person {
  return [[Person alloc] init];
}
@end

@interface Student : Person 
@property NSInteger no;
@end

int main() {
  Student *s = [Student person];  //这句相当于Student *s =[[Person alloc] init];而Person中是没有no属性的
  NSInteger *no = s.no;  //这句会报错
}

总结:类工厂方法,最好不要用类名来创建,正确做法:

+ (instancetype)person {
  return [[self alloc] init];
}

9、类

(1)、类的本质:
类也是一个对象,这个对象会在类第一次被使用时创建,只要有了类对象,以后就可以通过类对象来创建实例对象,而实例对象中有一个isa指针,指向自己的类对象
(2)、作用:
类对象中保存了当前对象所有的对象方法,当给一个实例对象方法消息的时候,会根据实例对象中的isa指针去对应的类对象中查找。
(3)、isa与类继承关系

三种对象

类对象中存储属性与对象方法,元类对象存储类方法,实例对象调用方法时根据isa指针来从类对象或者元类对象中查找方法进行调用。

例子

10、@class与#import

区别:@class只是告诉编译器这是一个类,不会将这个类拷贝到另一个类中,而#import会将类的代码拷贝到另一个中,因为@class不拷贝,所以不能访问类中属性与方法。

1)、如果A类拷贝了B类,B类拷贝了C类,如果C类做了修改,那么A类和B类都会重新拷贝一次C类,如果#import放在了.h文件中,那么有间接关系的类,都会重新拷贝
2)、如果在.h文件中用@class在.m文件中使用#import,如果一个文件发生了修改,那么只有直接引用这个文件的类才会重新拷贝,间接引用的类不会去重新拷贝,所以合理使用@class能提升编译效率
3)、@class能有效避免文件循环导入,如果A导入B,B导入A,会造成编译器报错,所以此时应该在.h文件中用@class在.m文件中用#import,这样能避免循环导入

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,932评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,554评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,894评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,442评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,347评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,899评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,325评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,980评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,196评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,163评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,085评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,826评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,389评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,501评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,753评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,171评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,616评论 2 339

推荐阅读更多精彩内容