Objective-C面向对象浅谈

来源:互联网 发布:电商美工的目的 编辑:程序博客网 时间:2024/04/26 17:59

本文简述了Objective-C语言的语法(偏面向对象),以及一些个人见解。

Objective-C(之后称OC),顾名思义,是C语言面向对象的一种扩展,它保留了C语言的全部语法,并且兼容C语言,在这基础上建立了一套完整的面向对象编程体系。

在面向对象相关的语言层面上,可以说它是比较像Java的:单继承、有接口等。但是在代码中,它跟C++是比较相似的。

让我们来看代码吧!

#import <UIKit/UIKit.h>#import "MyClass.h"int main(int argc, char * argv[]) {    @autoreleasepool {        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));    }}

可以看出,对于库文件、自己创建的类的引用使用了“import”关键字。这里可以说OC虽然完全支持C语言,但是一些细节OC也做了相关的优化,这里不具体陈述,我们使用其推荐的即可。
还可以看到“@autoreleasepool”关键字,OC使用“@”来标识其特有的一些关键字以及特殊用法,如:“@interface”、 “@property”、 “@protocol” 等,可以说“@”在OC中无处不在。

接下来说一下OC的面向对象特性。
作为一个面向对象语言,其面向对象特性我们不得不提,我们从继承、封装以及多态来谈其面向对象特性。

首先,需要介绍其基本的面向对象语言特性,下面来看一些基本代码:

//head file:demo.h#import <Foundation/Foundation.h>@interface TestClass : NSObject <NSObject>//继承NSObject类(第一个),遵守NSObject协议(第二个)@property (nonatomic) NSInteger value;- (void)replaceTheValueWithValue:(NSInteger)value;@end
//source file:demo.m#import <Foundation/Foundation.h>@implementation TestClass- (void)replaceTheValueWithValue:(NSInteger)value {    self.value = value;}@end
//source file:main.m#import <Foundation/Foundation.h>#import "demo.h"int main(int argc, const char * argv[]) {    @autoreleasepool {        TestClass *obj = [[TestClass alloc] init];        obj.value = 1;        NSLog(@"%ld", (long)obj.value);        [obj replaceTheValueWithValue:1];        NSLog(@"%ld", (long)obj.value);    }}

以上代码展示了一个非常简单的类“TestClass”的定义及其简单的使用。
“Demo.h”文件给出了类的声明,并作为一个“类的说明书”供使用者参考,而“Demo.m”文件则是给出类的定义(需要实现的部分),即给出类的必要部分的实现细节。笔者前面提到的OC与C++类似的部分就在于次。
“main.m”文件则是类似于C语言一个拥有主函数的文件,它确实拥有“main”函数,作为程序的入口。其中有对象的创建、对象属性的使用、对象方法的调用,读者可以进行一下参考。
代码中如果有不明白的地方可以自行研究。
下面将简介其面向对象特性:
1.继承
OC完全支持面向对象的继承特性,并且与Java语言类似,引入了类似于“接口”的“协议”。当然,本文不探讨其真正的共同点与不同点,只是拿来做参考。
下面通过代码来学习:

//为了简化代码,将把所有内容写入一个源文件//source code:main.m#import <Foundation/Foundation.h>@protocol TestProtocol <NSObject>@optional- (BOOL)valueFlag;@required- (void) replaceTheValueWithValue:(NSInteger)value;@end@interface TestClass : NSObject <TestProtocol>@property (nonatomic) NSInteger value;@end@implementation TestClass- (instancetype)init {    self = [self initWithValue:0];    return self;}- (instancetype)initWithValue:(NSInteger)value {    self = [super init];    if (self != nil) {        self.value = value;    }    return self;}- (void)replaceTheValueWithValue:(NSInteger)value {    self.value = value;}@endint main(int argc, const char * argv[]) {    @autoreleasepool {        TestClass *obj = [[TestClass alloc] initWithValue:3];        obj.value = 1;        NSLog(@"%ld", (long)obj.value);        [obj replaceTheValueWithValue:1];        NSLog(@"%ld", (long)obj.value);    }    return 0;}

这里引入了一个叫“TestProtocol”的协议,而新的“TestClass”需要遵守这个协议。其中拥有一些可选(optional)和必须(required)实现的方法。
有关继承,这里使“TestClass”继承了“NSObject”类(事实证明OC中所有的类的最终基类一定是NSObject),它提供给我们的类很多已经实现的东西(比如实例化时的内存分配方法“alloc”),OC是单继承,我们可以用协议来丰富类的方法约束,以及完成一些特殊设计模式的需求。
2.封装
说到封装,我们就不得不提面向对象语言的访问控制,这一部分看似是比较容易的(在C++中,只需要搞清楚“public”、“protected”和“private”的区别并应用到实际设计中),但是在OC(以及新的Swift)中并不是如此,下面还是通过一段代码来说明。

#import <Foundation/Foundation.h>@interface TestClass : NSObject {@private    NSInteger _value2;@protected    NSInteger _value3;@public    NSInteger _value4;@package    NSInteger _value5;}@property (nonatomic) NSInteger value;@end@implementation TestClass- (void)replaceTheValueWithValue:(NSInteger)value {    self.value = value;}@endint main(int argc, const char * argv[]) {    @autoreleasepool {        TestClass *obj = [[TestClass alloc] init];        obj.value = 1;//        obj->_value2 = 1; //error//        obj->_value3 = 1; //error        obj->_value4 = 1;        obj->_value5 = 1;        [obj replaceTheValueWithValue:1];    }    return 0;}

OC也拥有类似C++的“public”、“private”、“protected”关键字,只是表现形式不一样。而且OC增加了“@package”关键字,用以表示在该程序包(类似一个依赖库一样)内显公有,对外显私有的状态。
OC的“属性”默认访问控制模式为“@protected”,而“方法”的默认访问控制模式为“@public”,但是为什么上面的属性“value”却可以使用“.”运算符“访问”呢?因为“@property”关键字会为该属性自动生成存取方法,而方法的默认访问控制模式为“@public”,因此可以通过特殊的运算符“.”来访问。(同理大家可以试试访问方法的语法“[obj value]”和“[obj setValue:val]”是否可以用!)
综上所述,OC实现封装还是非常容易的。
3.多态
多态的实现其实对于OC并不难。首先我们可以创建一个普通的类(区别于虚类),然后用多个子类继承它,再写出类似

BaseClass *obj;obj = [[SubClass1 alloc] init];obj = [[SubClass2 alloc] init];

的代码来实现多态。但是这样子如果“BaseClass”中需要有纯虚函数,虽然可以不写具体实现来忽略它,但是这样不是最佳的做法,因此我们可以用OC的“协议”来实现对纯虚函数的要求,以及多态的实现,下面通过代码来演示。

#import <Foundation/Foundation.h>@protocol BaseProtocol <NSObject>@required- (void)call;@end@interface BaseClass : NSObject@property (nonatomic, copy) NSString *name;@end@interface Dog : BaseClass <BaseProtocol>//It's own interface like kill@end@interface Cat : BaseClass <BaseProtocol>//It's own interface like jump@end@implementation BaseClass- (instancetype)initWithName:(NSString *)name {    self = [super init];    if (self) {        self.name = name;    }    return self;}@end@implementation Dog- (void)call {    NSLog(@"%@: Wang!", self.name);}@end@implementation Cat- (void)call {    NSLog(@"%@: Miao!", self.name);}@endint main(int argc, const char * argv[]) {    @autoreleasepool {        BaseClass <BaseProtocol> *animal;        animal = [[Dog alloc] initWithName:@"tom"];        [animal call];        animal = [[Cat alloc] initWithName:@"jerry"];        [animal call];    }    return 0;}

可以看到,主函数中给出了运用多态的对象animal(在第57和59行调用“叫”的方法时我们不需要知道是什么在叫,只需要知道它会叫即可)而它可以实例化为其子类的对象。

如有不对敬请指出,感谢阅读!

0 0