ObjC: 源文件的组织
转自:http://marshal.easymorse.com/tech/objc-%e6%ba%90%e6%96%87%e4%bb%b6%e7%9a%84%e7%bb%84%e7%bb%87
最简单的ObjC程序,你都可以这样写:
#import <Foundation/Foundation.h>
@interface Book : NSObject{
}
-(NSString *) getPrice;
@end
@implementation Book
-(NSString *) getPrice{
return @"$17";
}@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];Book *book=[[Book alloc] init];
NSLog(@"Book price: %@",[book getPrice]);
[pool drain];
return 0;
}
理论上讲,按照上面的写法,你可以把所有的代码都写在一个文件里。
但是问题是,你不便于维护这个代码。代码很长,很乱。
所以,一般有以下几种形式来拆分和组织代码:
- 类文件拆分为头文件和m文件
- 使用组的概念来管理文件
拆分接口和实现部分
拆分h文件和m文件很好理解。只要使用Xcode做开发,通过向导页面创建类,文件默认情况下就是强制分开的:
使用组的概念管理文件
使用组的概念。在Xcode下面,程序源文件都是放在Source目录下的,在该目录下,可以进一步创建“目录”,把不同用途的源文件分类放置。这样就如同桌上凌乱的书归置到书架里一样。很好查找和查阅。
可以看到,下面是把Book相关的一些类放在book组中了。
这个组看起来是目录,但如果你打开finder,查看目录结构,发现并不存在这样的目录:
拆分文件带来的问题及解决办法
拆分文件带来很多好处。不只是自己看着方便了,还能方便多人合作开发。如果多人修改一个文件,很容易出现各种问题。每个人负责自己的代码文件,这些文件组成一个项目,这样就不容易造成文件版本上的冲突。
但是,这也带来了新的问题。一个文件依赖另外一个文件的时候,需要通过import来导入。比如:
#import <Foundation/Foundation.h>
#import "CategoryDemo.h"
#import "Book.h"
#import "MusicBook.h"
#import "PlayMusic.h"@class Author;
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];NSString *message=@"你好,世界!";
NSLog(@"%@, 长度为: %i",message,[message length]);
[message printHelloInfo];Book *book=[[Book alloc] init];
这里main方法中使用了Book类,那么,就需要通过import把它引进来,否则,编译器不知道Book类在哪里。
另外,如果我这样:
#import <Foundation/Foundation.h>
#import "CategoryDemo.h"
//#import "Book.h"
#import "MusicBook.h"
#import "PlayMusic.h"@class Author;
int main (int argc, const char * argv[]) {
注释了对Book头文件的导入,系统一样编译通过,而且运行正常。这是怎么回事儿呢?
这是因为编译器很聪明。它发现MusicBook头文件里面已经导入了Book头文件:
#import <Cocoa/Cocoa.h>
#import "Book.h"
#import "PlayMusic.h"@interface MusicBook : Book <PlayMusic>{
在上面代码中有一个奇怪的代码:
@class Author;
有了这句话,该代码中的:
book.author=[[Author alloc]init];
就不会报错了。
可以用下面的语句替代@class的代码:
#import "Author.h"
//@class Author;
系统一样会很好的工作。那么,@class和#import有什么区别呢?
这里要说一下头文件依赖关系。如果有100个m文件都导入了某个头文件,那么,当这个头文件改变了内容,则编译器会强制重新编译这100个m文件的。编译的速度可想而知。
@class就是为了避免这样的事情发生的。当编译器看到比如类文件B是通过@class的方式引入一个类文件A,就不会在该类文件A的头文件改动后重新编译B了。
那如果这样,都用@class替代#import吧。问题是,有些情况,只能使用#import。因为有时候编译器不只是需要知道类B引用到类A,还需要知道类A的内部信息,而这些信息是类B需要的。比如类B继承自类A,这时就不能用@class,而只能用#import。
ObjC: 源文件的组织的更多相关文章
- “前.NET Core时代”如何实现跨平台代码重用 ——源文件重用
微软在2002年推出了第一个版本的 .NET Framework,这是一个主要面向Windows 桌面(Windows Forms)和服务器(ASP.NET Web Forms)的基础框架.在此之后, ...
- Google软件构建工具Bazel FAQ
Google软件构建工具Bazel FAQ 本文是我的翻译,原文在这里.欢迎转载,转载请注名本文作者和原始链接 注:如果想了解Bazel的原理,可以看看我之前翻译的Google Blaze原理及使用方 ...
- C++生成二级制文件过程(预处理->编译->链接 )
转载请注明出处 Windows下C++编程,通过VC生成工程,编写C++源文件,点运行,代码没问题直接出结果.VC什么都帮我们搞了,不了解其中过程也完全没问题. 转到linux下写c++,总觉得有点虚 ...
- Google软件构建工具Bazel
转载Google软件构建工具Bazel FAQ 本文是我的翻译,原文在这里.欢迎转载,转载请注名本文作者和原始链接注:如果想了解Bazel的原理,可以看看我之前翻译的Google Blaze原理及使用 ...
- .NET Core跨平台的奥秘[中篇]:复用之殇
在<.NET Core跨平台的奥秘[上篇]:历史的枷锁>中我们谈到:由于.NET是建立在CLI这一标准的规范之上,所以它天生就具有了"跨平台"的基因.在微软发布了第一个 ...
- Objective-C 基础教程第六章,源文件组织
目录 Object-C 基础教程第六章,源文件组织 0x00:前言 0x01:Xcode创建OC类 0x02:Xcode群组 0x03 Xcode跨文件依赖关系 @class关键字 导入和继承 小结 ...
- 明白python文件如何组织,理解建立源文件
在Python 中引用是非常简单的事情,这里需要清楚三个概念就可以了包.模块.类.类这个就不用说了. 模块对应的是一个.py 文件,那么module_name 就是这个文件去掉.py 之后的文件名,p ...
- 【转】开篇python--明白python文件如何组织,理解建立源文件
在Python 中引用是非常简单的事情,这里需要清楚三个概念就可以了包.模块.类.类这个就不用说了. 模块对应的是一个.py 文件,那么module_name 就是这个文件去掉.py 之后的文件名,p ...
- @OBJC 和 DYNAMIC
原文转载自:@OBJC 和 DYNAMIC 虽然说 Swift 语言的初衷是希望能摆脱 Objective-C 的沉重的历史包袱和约束,但是不可否认的是经过了二十多年的洗礼,Cocoa 框架早就烙上了 ...
随机推荐
- 使用Git管理品优购项目 开始部分
- NOIP 2003 栈
洛谷 P1044 栈 洛谷传送门 JDOJ 1291: [NOIP2003]栈 T3 JDOJ传送门 题目描述 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表. 栈有两 ...
- Hibernate框架学习2
集合映射 public class User { // 一个用户,对应的多个地址 private Set<String> address; private List<String&g ...
- MongoDB executionStats 详细分步查询计划与分步时间(转载)
mongodb性能分析方法:explain() 为了演示的效果,我们先来创建一个有200万个文档的记录.(我自己的电脑耗了15分钟左右插入完成.如果你想插更多的文档也没问题,只要有耐心等就可以了.) ...
- 掌握Visual Studio断点
我知道你现在在想什么.断点?真的吗?关于断点有什么需要掌握的?你按F9然后停在代码行.如果你是这么想的,这篇文章是给你的:继续读 Visual Studio提供了一组相当丰富的断点类型和操作,可以使您 ...
- plv8 centos install steps
install deps yum -y update yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL- ...
- [RN] React Native 中使用 stickyHeaderIndices 实现 ScrollView 的吸顶效果
React Native中,ScrollView组件可以使用 stickyHeaderIndices 轻松实现 sticky 效果. 例如下面代码中: <ScrollView showsVert ...
- localStorage二次封装-----设置过期时间
export default{ set(key,data,time){ let obj={ data=data, ctime:(new Date()).getTime(),//时间戳,同Date.no ...
- Codeforces Global Round 3 题解
这场比赛让我上橙了. 前三题都是大水题,不说了. 第四题有点难想,即使想到了也不能保证是对的.(所以说下面D的做法可能是错的) E的难度是 $2300$,但是感觉很简单啊???说好的歪果仁擅长构造的呢 ...
- Linux学习之编译运行.c(C语言)文件
在Linux命令行界面下,创建文件hello.c,进入vim编辑器,编辑一个简单的C语言文件 分解C语言文件执行过程,要经过预编译.编译.汇编.连接四个步骤后才能执行, 预编译:gcc -E hell ...