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 框架早就烙上了 ...
随机推荐
- split分割字符串返回字符串数组
<script type="text/javascript"> var str='liu jin yu'; var str1=str.split(' '); docum ...
- python nose 自写插件打乱class类中用例执行顺序,但将test_a和test_z排除
在使用nose时,有这样一个需求,用例执行打乱,但部分用例因场景原因必须先执行,这类用例在写用例时人为的加上了test_a或test_z字样 网上找了一圈,都没找到合适的方法,只有自己写插件了 已写完 ...
- CUDA10安装配置
https://developer.nvidia.com/cuda-downloads?target_os=Windows&target_arch=x86_64&target_vers ...
- DS18B20温度获取
https://detail.tmall.com/item.htm?id=40083203373&spm=a1z09.2.0.0.31cd2e8d1sb06V&_u=e1qf7bf56 ...
- Jmeter函数助手—自带方法
1.${__time()}---->当前时间,一串数字格式 2.${__time(yyyy-MM-dd)}----->当前日期,年-月-日格式 3.${__time(yyyy-MM-dd ...
- STL——list用法总结
头文件 #include<list> 声明一个int型的list:list<int> a: 1.list的构造函数 list<int>a{1,2,3} list&l ...
- 网络协议 7 - UDP 协议
网络协议五步登天路,我们一路迈过了物理层.链路层,今天终于到了传输层.从这一层开始,很多知识应该都是服务端开发必备的知识了,今天我们就一起来梳理下. 其实,讲到 UDP,就少不了 TCP.这俩 ...
- 微信网页分享使用了jssdk,分享图还是不显示的几个坑
坑爹的微信分享,设置图片链接必须要满足如下条件: 1. 微信分享图链接必须是绝对路径,写相对地址不行. 比如图片地址写成 './assets/images/share.jpg' 不行!!! 必须写成 ...
- Unix/Linux小计
1. centos查看cpu信息 cat /proc/cpuinfo processor有几个就是有几个cpu,每一列是每个cpu的信息 每个processor中的cores是当前cpu中有几个核心. ...
- 快速搭建Linux-0.11实验环境
搭这个实验环境主要是为了学习Linux-0.11的代码,那就需要修改代码再次编译来验证自己的想法.主要的实验环境来自实验楼,但是在那上面毕竟不方便,所以就以实验楼上的为基础在自己的虚拟机上搭建一个环境 ...