小弟初学objective-c,对于extension的作用一直无法理解,请各位前辈指点一二。

2013-08-31 09:45:05 +08:00
 meta
看到很多书上都说,扩展可以用来实现类的私有实例变量和方法,那么把方法从.h文件中去掉,使其不被引用到,不就实现私有方法了么,为什么要写成扩展的方式呢。
又看到有说如果可以在.h中将属性置为readonly而在.m的扩展中再设置为readwrite,这样就能保证属性对外部是只读的而对内部是读写的,但是只要在.m中写个@synthesize x = _x;不也能达到这样的效果么。

所以对使用扩展到底有什么用处一直搞不明白,请各位赐教。
2208 次点击
所在节点    C
28 条回复
xhacker
2013-08-31 10:07:38 +08:00
从 .h 里去掉就要放在 extension 里啊。
property 就是自动生成 synthesize 的,不用手动写。
meta
2013-08-31 10:19:46 +08:00
@xhacker extention不是要写成:@interface XXXClass()吗,我的意思是说不这样写又有什么区别呢。
property那个不这样写的话怎么实现外部只读,内部可读写的功能呢?
xhacker
2013-08-31 10:22:56 +08:00
不写成 extension 你想怎么写?
property 就按你说的那么写就对,我是说不应当手动写 synthesize。
meta
2013-08-31 10:29:26 +08:00
@xhacker 比如:

//Base.h
@interface Base : NSObject
@property int x;

@end


//Base.m
@implementation Base

@synthesize x = _x;

-(int) fetchX{
return _x;
}
@end

这样不是私有方法么,和扩展的区别是什么呢。
xhacker
2013-08-31 10:32:56 +08:00
@meta: 这样不是私有,外面可以访问到吧。
另外 getter 应该叫 x 而不是什么 fetchX。
meta
2013-08-31 10:36:14 +08:00
@xhacker .h文件里面没有,外面怎么访问呢。
写成fetchX就是为了和getX区别,好显示效果,getX就是存取方法了,不好测试。
walkingway
2013-08-31 11:04:44 +08:00
@property 和 @synthesize的作用就是生成一对getter 和 setter方法,你在.h里声明了一个@property 其实就声明一个实例变量的getter和setter方法,新的LLVM下已经不用手动再去.m里写@synthesize了(当然如果你手动重载了getter和setter,是要写的)

你虽然写了个fetchX,但你在.h里声明了个@property,外面还是能通过getter方法访问的。
xhacker
2013-08-31 11:10:29 +08:00
@meta: 简而言之很简单:要 public 就把 property 写 .h 里,要 private 就写 .m 里,要对外只读就在 .h 里写 readonly、.m 里写 readwrite。
meta
2013-08-31 12:22:40 +08:00
看来楼上两位没有明白我的问题,自动生成的setter和getter显然是public的,这个我清楚。我疑惑的是extension该用在什么地方的问题,所以请不要纠结那个property。

可能是我举例不太恰当,有些误导,现在我来重新写一下。

问题一、方法的作用域的问题

//-----1-----
//Base.h
@interface Base : NSObject{
int x;
}

@end


//Base.m

@interface Base()
-(int) fetchX;
@end

@implementation Base

-(int) fetchX{
return x;
}
@end


//-----2-----
//Base.h
@interface Base : NSObject{
int x;
}

@end


//Base.m
@implementation Base

-(int) fetchX{
return x;
}
@end


写法1是我在书上看到的是用扩展的一个场景,说是可以讲fetchX置为私有,但我认为写法2也可以,请问以上两种写法的区别在哪里。

问题二、改变属性存取权限的问题
//-----1-----

//Base.h
@interface Base : NSObject
@property (readonly)int x;

@end


//Base.m

@interface Base()
@property (readwrite)int x;
@end

@implementation Base
@end

//-----2-----
//Base.h
@interface Base : NSObject
@property (readonly)int x;

@end


//Base.m

@implementation Base
@synthesize int x=_x;
@end


写法1是我在网上找到的另一个应用扩展的场景,可以将readonly的x变成内部readwrite,但我认为写法2直接内部访问_x也可以达到同样的效果,请问这两种写法有什么不同吗。

由此,我一直不理解到底什么场景应该使用扩展。
ldehai
2013-08-31 12:29:26 +08:00
顾名思义,扩展就是扩展已有类的功能。这个已有的类一般来说都不是自己写的,要么是系统基础类,要么是第三方的类,这个时候想要增加这个类的功能就用扩展。

你所说的“扩展可以用来实现类的私有实例变量和方法“,只是说用扩展可以这么实现,不是说用其他方式不能实现。我觉得这不是扩展设计的初衷。
ldehai
2013-08-31 12:46:33 +08:00
给个例子你参考一下,一个UIColor类的扩展:https://github.com/ldehai/UIColor-Categories

使用的时候给一个按钮设置背景颜色
btn.backgroundColor = [UIColor colorWithHexString:@"#E0E4CC"];
ichord
2013-08-31 12:58:10 +08:00
首先, 我也是初学者, 只是看到你的问题也顺便查阅资料学习学习. 纯讨论哈.

@ldehai 你说的是 `category` 吧. `extension` 才是用于扩展自己写的类的啊.

@meta 我觉得你没有考虑继承的问题, 面向对象很基础的问题吧. 私有的东西是不被继承的吧.
* 类变量默认是 `protected` 的.
* `extension` 是不被子类继承的(除非你引入它的 .h 文件)

所以

And...
meta
2013-08-31 12:59:12 +08:00
@ldehai 你这个例子是category啊,category我能理解,我不理解的是extension,extension和原来的类是不能分开实现的,不能像这个例子中这么做。
ichord
2013-08-31 12:59:36 +08:00
= =.... 我还没编辑完......
anyway. 反正大概意思算是表达了.
meta
2013-08-31 13:01:20 +08:00
@ichord 写在.h中的变量才是protected的吧,写在.m中的变量不应该是private的吗?
ichord
2013-08-31 13:01:58 +08:00
再补一条, 我在 <Programming iOS> 的 objective-c 章节里看到. 用 synthesize 自动生成的 instance variable 也默认是 private 的.....
meta
2013-08-31 13:03:43 +08:00
@ichord 是的,所以说加上extension有什么作用呢。
ichord
2013-08-31 13:03:43 +08:00
@meta 我也搞不清楚. 先吃饭去. 待会回来写个例子一一验证好了.
ultragtx
2013-08-31 13:55:08 +08:00
看文档去 文档里都写了
chchwy
2013-08-31 16:57:59 +08:00
首先你要明白一件事,最近兩三年Objective-C的語言演進很快,extension是舊時代留下來的產物。

Xcode 4.2/LLVM 3.0 之後Objc語言引進了非常多新特性,語法也有相當變化。

詳細可查看這張表:
https://developer.apple.com/library/ios/releasenotes/ObjectiveC/ObjCAvailabilityIndex/

Xcode 4.2 是 2011年10月發佈的,我猜你的書的出版日期可能在這之前。

1. 以前只把方法和變量從.h移走,是沒辦法通過編譯的,私有方法一定要放在extension裡。
2. 現在私有變量、私有方法都直接寫在@implementation block裡就好了,但是這都是在Xcode 4.2之後才有的功能,以前不能這樣寫的。
3. 現在extension已經成了雞肋般的存在。唯一的用途就是有個類似.h的方法列表,閱讀上比較容易。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/80831

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX