1
xhacker 2013-08-31 10:07:38 +08:00 via iPad 1
从 .h 里去掉就要放在 extension 里啊。
property 就是自动生成 synthesize 的,不用手动写。 |
2
meta OP @xhacker extention不是要写成:@interface XXXClass()吗,我的意思是说不这样写又有什么区别呢。
property那个不这样写的话怎么实现外部只读,内部可读写的功能呢? |
3
xhacker 2013-08-31 10:22:56 +08:00
不写成 extension 你想怎么写?
property 就按你说的那么写就对,我是说不应当手动写 synthesize。 |
4
meta OP @xhacker 比如:
//Base.h @interface Base : NSObject @property int x; @end //Base.m @implementation Base @synthesize x = _x; -(int) fetchX{ return _x; } @end 这样不是私有方法么,和扩展的区别是什么呢。 |
6
meta OP @xhacker .h文件里面没有,外面怎么访问呢。
写成fetchX就是为了和getX区别,好显示效果,getX就是存取方法了,不好测试。 |
7
walkingway 2013-08-31 11:04:44 +08:00 1
@property 和 @synthesize的作用就是生成一对getter 和 setter方法,你在.h里声明了一个@property 其实就声明一个实例变量的getter和setter方法,新的LLVM下已经不用手动再去.m里写@synthesize了(当然如果你手动重载了getter和setter,是要写的)
你虽然写了个fetchX,但你在.h里声明了个@property,外面还是能通过getter方法访问的。 |
8
xhacker 2013-08-31 11:10:29 +08:00
@meta: 简而言之很简单:要 public 就把 property 写 .h 里,要 private 就写 .m 里,要对外只读就在 .h 里写 readonly、.m 里写 readwrite。
|
9
meta OP 看来楼上两位没有明白我的问题,自动生成的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也可以达到同样的效果,请问这两种写法有什么不同吗。 由此,我一直不理解到底什么场景应该使用扩展。 |
10
ldehai 2013-08-31 12:29:26 +08:00
顾名思义,扩展就是扩展已有类的功能。这个已有的类一般来说都不是自己写的,要么是系统基础类,要么是第三方的类,这个时候想要增加这个类的功能就用扩展。
你所说的“扩展可以用来实现类的私有实例变量和方法“,只是说用扩展可以这么实现,不是说用其他方式不能实现。我觉得这不是扩展设计的初衷。 |
11
ldehai 2013-08-31 12:46:33 +08:00
给个例子你参考一下,一个UIColor类的扩展:https://github.com/ldehai/UIColor-Categories
使用的时候给一个按钮设置背景颜色 btn.backgroundColor = [UIColor colorWithHexString:@"#E0E4CC"]; |
12
ichord 2013-08-31 12:58:10 +08:00
|
13
meta OP @ldehai 你这个例子是category啊,category我能理解,我不理解的是extension,extension和原来的类是不能分开实现的,不能像这个例子中这么做。
|
14
ichord 2013-08-31 12:59:36 +08:00 1
= =.... 我还没编辑完......
anyway. 反正大概意思算是表达了. |
16
ichord 2013-08-31 13:01:58 +08:00
再补一条, 我在 <Programming iOS> 的 objective-c 章节里看到. 用 synthesize 自动生成的 instance variable 也默认是 private 的.....
|
19
ultragtx 2013-08-31 13:55:08 +08:00
看文档去 文档里都写了
|
20
chchwy 2013-08-31 16:57:59 +08:00 2
首先你要明白一件事,最近兩三年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的方法列表,閱讀上比較容易。 |
21
ichord 2013-08-31 17:05:07 +08:00
@meta 在实现的效果上我也完全找不到有什么区别了. 我也求解答!
书上和网上的例子能看出的却别也就是用法概念之类的问题.. https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html#//apple_ref/doc/uid/TP40011210-CH6-SW6 看这个官方的例子, 实际实现效果的区别也就是只有类内部可以使用 `[self setProperty:xxx]` 或者 `self.property = xxx` 这样的用法而已. ---- * 在 @interface 声明的 instance variable 是 protected 的. * 在 @implement 声明的 instance variable 是 "private" 的. * @synthesize 自动声明的 instance variable 也是 "private" 的. * objective-c 里面的类方法只有两种: ** 在 @interface 声明的. "public" ** 没在 @interface 声明的. "private". (其实是没有这个概念的是吧?!) 所以要声明 instance variable 或者 method 为私有的(private) 的话, 根本没必要在 class extension 的声明. ---- 我在 <Learning Cocoa with Objective-c> 的 `Class Extensions` 章节看到这两句话: > there are two reasons for extending a class: 1. You want to add extra behavior and logic to an existing class 2. You want to break up one of your own classes into separate components. 我现在能想到的就是 1. 配合 `category` 将一个大类进行各种拆分组合, 类似于 `Mixin` 的用法. 因为 `category` 可以创建方法但不能创建类变量, 而另一个则可以创建类变量但不能创建方法. 而且方法声明貌似没什么用处... 2. 将一个大类以不同的 @interface 组合暴露出去, 按适用需要 `import` (这个貌似也很弱的样子... = =) = =. 今天就先到这好了... 以后遇到再说... |
23
xuzhe 2013-08-31 19:12:43 +08:00 1
首先,
_x = a; 和 self.x = a; 的区别你理解了吗? 这个能理解的话,你的问题应该自己也能想明白了。 |
24
walkingway 2013-08-31 19:58:20 +08:00
你举的两个例子:
第一个 1和2 没有什么区别,只要不在.h里的方法默认都是私有方法 第二个 你真正理解为什么要用 @synthesize x = _x 而不是 @synthesize x么? 这么做的目的是为了方便区分属性x和实例变量_x而已,仅此而已。 你在.h里声明x了只读,在.m的扩展里不改写为读写的话,是无法用self.x=...来赋值的。当然你说你直接用_x=...来赋值可以,但是,这么做也就跳过了getter和setter方法,当然不受readonly的限制。 如果你getter和setter方法里做点特别的事情,你用_x就没法和self.x达到一样的效果了。 不知道说明白没 |
25
walkingway 2013-08-31 20:07:03 +08:00
简单说就是 self.x 和 self.x = ... 调用的是@property 生成的getter和setter方法,
@synthesize x = _x 生成一个实例变量,为了不和属性x混淆改名为_x,以后你写_x就是直接访问的实例变量,不会调用getter和setter方法。你getter和setter方法里做的一些额外事情,也无法实现。 |
26
xsown 2013-09-01 01:15:12 +08:00 1
1) 用 extension 的方式在 .m 文件里把一个 property 从 readonly 改为 readwrite,改变的是这个 property 本身,这时候你就可以写 self.someProperty = xxx 而不会引起编译器报错。
2) 如果你把这个 property 给手动 synthesize 到某个 ivar 上,然后修改 ivar 的值,表面上看确实与 readwrite 的效果等同。但是 property 上面的修饰词可能会造成一些区别,比如 atomic,那么当你写 self.someProperty = xxx 时,编译器实现的代码会是类似 someLockFunction(); _someProperty = xxx; someUnlockFunction(); 这样的形式,确保不同的线程同时访问这个 property 时不会出错。 3) property 作为一种封装,getter 和 setter 有很大的自由度可以实现复杂的行为。而对 ivar 的读写仅仅是取值/赋值。所以 readwrite 化的 property 更加灵活。 |
27
meta OP 非常感谢楼上各位,@chchwy 完全解决了我的疑惑,@walkingway 和@xsown 的解答也很有价值。我不是不了解属性和实例变量的区别,我疑惑的是使用场景,因为私有的属性和公有的属性使用场景是完全不一样,我不明白在什么场景需要用到私有的属性而不使用变量,固然可以简单的用self.x访问到自定义的getter和setter方法,但是这样比直接使用setX也简单不到哪里去。@xsowm说的线程安全的问题很有道理,但我认为既然是私有变量,不需像对外的接口一样需要形式上的一致,那么处理方法多种多样,没看出来一定要使用extension的理由。所以@chchwy 兄的介绍就让我完全明白了。
这次真是获益匪浅,非常感谢大家。 |
28
xuzhe 2013-09-01 10:11:02 +08:00
很明显 chchwy 同学也没完全搞明白,他的第3点总结是不对的。
楼上几位都说得那么清楚了,可 @meta 同学还是总结出“没看出来一定要使用extension的理由“,好吧。 |
29
vixvix 2013-09-01 12:11:46 +08:00
extension跟category的区别是可以加ivar和properties. 这个特别属性使得在interface决定的情况下,不许要做大的修改你也可以给这个interface添加需要的功能。
在大型项目或者外包项目中,interface在项目组或者公司间定下后通常就很少修改,这时你要扩展功能用extension就可以很容易的添加ivar或者properties。你或者可以使用外部singleton,但可读性和可维护性相对与extention就会差很多。 |