C语言添加面向对象特性,OC语言中面向对象有三大特性

OC语言中面向对象有三大特性,分别是封装,继承和多态。

(一)封装:

成员变量有四种作用域类型,分别是@public,@private,@protected和@package。

a4c26d1e5885305701be709a3d33442f.png

之前我们定义好成员变量后,想要在main中直接访问成员变量,往往要在成员变量的定义时候加上一个@public,这种做法虽然可以实现访问,可是它会让你的数据变得很透明,不仅可以随意被访问而且有可能会变得很不合理,例如我顶一个一个int类型的age年龄属性,在主函数main中把age赋值成-10,这都是可以的。所以,为了保证数据的不透明习惯,安全性和合理性。我们一般不适用@Public来使得外界获得访问权利。而是提供一种封装方法来供外界使用访问我们内部的成员变量。这些方法成为setter和getter。它们就是我们的封装。

1.setter和getter的声明:

@interfacePerson

: NSObject

{

int_age;

}

- (void)setAge:(int)age;

- (int)age;

@end

由上我们可以总结setter和getter的声明规范和一些注意点。首先,setter是更改成员变量属性,所以不需要返回值并且一定要传入一个和成员变量数据类型相同的参数。同时遵循方法命名规范:一个参数一个分号,数据类型用小括号括起来。而getter的作用是获得成员变量的值,所以不需要传入参数,并且一定有返回值,返回值为成员变量的数据类型。我们定义的成员变量是已下滑线开头的,它相应的getter和setter则不需要下划线。

2.setter和getter的实现:

@implementationPerson

- (void)setAge:(int)age

{

_age = age;

}

- (int)age

{

return_age;

}

@end

由上我们可以总结setter和getter方法的实现规范。它们可以依靠代码来实现访问或者修改我们的内部成员变量的值。基本上,每定义一个成员变量,都要设置其相应的setter和getter方法。

3.Xcode高级功能自动实现setter和getter:

①自动生成get方法和set方法:

@propertyintage;

其实编译器是很“笨”的,你怎么写他就怎么生成。写如上代码,编译器看到后,就自动变成

- (void)setAge:(int)age;

- (int)age;

相应的,它也完成了setter和getter方法的实现。

- (void)setAge:(int)age

{

_age = age;

}

- (int)age

{

return_age;

}

Xcode遵循一点,“没有我就生成,有我就用你的”。当什么都不定义就一句@property

int age时,其实完成了三件事

·

定义了一个_age的成员变量。

·

声明了这个成员变量的getter和setter。

·

实现了这个成员变量的getter和setter。

②@synthesize是用于生成getter和setter的实现的。用在@implementation和@end之间。

@implementationPerson

@synthesizeage

= _age;

@end

我们分析下这句@synthesize age = _age;

--->第一个age表示实现age这个成员变量的set和get。后面的_age表示在实现中,访问_age。

如果只写@synthesize

age;就默认访问age而不是_age;如果此时没有写成员变量,就生成成员变量age。

③注意:

Xcode帮我们能够生成_age的原因是它要在get和set中访问调用。如果只写了set和get方法中的一个,另一个自动生成。则Xcode依旧自动生成_age。但是如果set和get方法都是自己写的,那就不会再生成了。

在OC编程学习中,用的最多的还是@property。它可以生成下划线成员变量,getter,setter方法的声明和实现。并且遵循我们习惯的书写规范(成员变量下划线开头)。剩下的仅作为了解。用了Xcode高级功能封装数据,可以节约出很多写垃圾代码的时间,把更多的时间集合在思想上。

4.如果一个成员变量只允许访问不允许修改,那么这个成员变量就是只读的。这时候我们只提供它的get方法不提供set方法就可以了。

5.OC的弱语法性:

①如果调用一个不存在的方法,编译可以通过,链接也可以通过,但是不能运行成功,会报一个经典的错误:unrecogined

selector sent

to intance。意思是给某个对象发送了一条不可识别的消息(方法)。这是一个编程中很经常遇到的错误。

[1  2] --->2去1里找方法,找不到就报错。

②如果只写了方法声明,没有写实现,编译链接是可以通过的。OC是在运行工程中才会检测对象有没有实现相应的方法。这时候会出现崩溃或者闪退现象。

③如果只写实现,不写声明。程序是可以运行成功的,但是不推荐。

④OC的本质还是面向过程的。

6.类方法:

①之前我们学习过以-开头的方法。这些方法都是由对象调用的,叫做对象方法。以+开头的是类方法。顾名思义,类方法由类来调用。类方法无需创建对象。不依赖于对象就能实现方法,所以某种程度上提高了性能。例如我要设计计算器的些许功能,求和求平方等等,这时候不需要成员变量的参与。这些方法都是类方法。

②类方法里只有方法,没有成员变量。所以类方法是决不能访问成员变量的。并且类方法和对象方法允许同名。

③类方法里自己调用自己,顾名思义,会产生死循环。

7.关键字self:

self是一个指针,指向调用当前方法的对象。说白了,就是当前对象/当前类。熟悉运用self,会感觉OC写起来“很方便”

·

使用

"self->成员变量名"访问当前方法调用的成员变量

·

使用

"[self方法名];"来调用方法(对象方法\类方法)

(二)继承:

继承其实并不陌生。@interface Car :NSObject

我们每次在创建类时候都要写一个:NSObject。这就是一个继承。NSObject是Car的父类,也叫做超类。如果A继承B,那么A就拥有了B的所有属性,包括成员变量和所有方法。

@interfacePerson:

NSObject

1.继承的好处和坏处:

①抽取重复代码。

②建立了类之间的关系。

③耦合性太强,两个类关系太密切。某个类不见了,另一个也就不能用了。所以说不是什么都可以随便继承。

2.之前我们通过new这个方法来实现类对对象的创建。其实new就是NSObjet的一个+类方法,通过继承,子类可以通过new方法获得创造对象的能力。

3.能否继承,可以套用一句话,A

B。例如学生是人,那么学生类就可以拥有人这个类的所有属性。如果不适用,那一般都不能继承。

4.因为子类继承父类,所以继承关系的类之间不允许拥有相同的成员变量,这样会产生重复定义的错误。

5.一个方法:重写-->子类重新实现父类的某个方法,覆盖父类以前的做法。调用某个对象方法时,优先是在当前对象中找方法。当前对象中没有才去父类中寻找。下面由代码完成重写:

①首先定义Person类

#import

@interfacePerson

:NSObject

- (void)

test;

@propertyintage;

@end

#import"Person.h"

@implementationPerson

- (void)

test

{

NSLog(@"我是Person父类");

}

@end

②定义Student类继承Person类

#import"Person.h"

@interfaceStudent

:Person

@end

#import"Student.h"

@implementationStudent

- (void)

test

{

NSLog(@"我是Student子类");

}

@end

由上代码。Student重写了Person的test函数。我们调用Student的test方法完成程序的执行。

#import

#import"Person.h"

#import"Student.h"

intmain()

{

Student*s

=[ [Student

alloc] init];

[s test];

return0;

}

执行结果:

2015-04-02 16:18:58.507

oo[734:136700]我是Student子类

若要是不重写test方法,则现在当前类Student中找test方法,没有后去父类Person中找,找到后完成程序的执行。

执行结果:

2015-04-02 16:18:58.507

oo[734:136700]我是Student子类

至此,我们了解到了重写的功能。他可以覆盖父类功能。但是并不删除父类的功能。甚至可以先调用父类功能在重写此功能。

6.继承和组合:

·

当两个类拥有相同的属性和方法时候,就可以把他们相同的东西抽到一个父类中。

·

当A类完全拥有B的属性时,例如人完全拥有学生的属性,那么学生就继承人

·

总的来说,子类的东西都要比父类多。因为可以再继承父类的基础上自己增加新的成员变量。

·

但不是一可以继承就是用继承,还有一种方法叫做组合。当A拥有B时,就是组合-->学生拥有成绩,他们的关系应该是组合。

组合指的是两个类不继承,但是一个类中得成员变量是另一个类。如下代码:

创建Student类继承Person,但是组合Score类

#import"Person.h"

#import"Score.h"

@interfaceStudent

: Person

{

NSString *_name;

Score *_score;

}

@end

Score类的声明:

#import

@interfaceScore

:NSObject

{

int_cScore;

int_ocScore;

}

@propertyintcScore;

@propertyintocScore;

@end

这样,Student类就拥有了Score成绩类的属性。到时候只需创建成绩对象,把成绩对象通过setScore的方法赋值给Student的成绩成员变量就可以了。

7.继承关键字super

super是父类的意思。用来调用父类的对象方法或类方法。当子类重写父类时,若想要保留父类的行为,往往用super。这时候我们再次重写一下上面的Student类中得test方法,代码如下:

#import"Student.h"

@implementationStudent

- (void)

test

{

[supertest];

NSLog(@"我是Student子类");

}

@end

程序输出结果为:

2015-04-02 16:35:58.970

oo[770:148770]我是Person父类

2015-04-02 16:35:58.971

oo[770:148770]我是Student子类

由此可见super的使用方法。

(三)多态:

多态是多种形态的意思。指的是父类指针指向子类对象的行为。例如上述的Student类继承Person类。

1.多态的定义实现如下:

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

NSObject *n = [[Person alloc] init];

NSObject *n1 = [[Student alloc] init];

代码执行后,会动态检测指针的真实类型。所以其实p还是学生类,n是人类型,n1是学生类型。

2.多态的好处:

使用多态后,函数里可以写入方法。当有猫,狗,鸟等等动物类时,若要想用一个函数实现吃这个行为。只需传入一个他们共同的父类Animal动物类,这样所有类都可以使用这个方法了。

voidfeed(Animal

*a)

{

[a eat];

}

这时候传入参数可以是任意动物类的子类。

3.多态的坏处:

不可以使用父类指针调用子类方法。会警告。编译器会认为这个指针是Anmial类型,是一个父类类型。从而去父类中寻找方法。但是方法是在子类中的。这种方法不推荐。

4.多态总结

·

无继承无多态。

·

·

代码体现:父类指针指向子类对象。

·

·

好处:函数/方法参数可以使用父类类型。

·

·

坏处:父类指针不可调用子类方法,除非强转。

·

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值