OC类方法与实例方法深度对比:开发必知的核心区别
刚学OC那会儿,你是不是也被这两个概念绕得头晕?明明都是方法,为啥有的要写[ClassName method],有的非得用[object method]?哎呦喂,我懂!当年我对着Xcode发愣的样子,活像看到菜单上写着"本店招牌菜"和"厨师特供"——根本分不清有啥区别嘛!
(敲黑板)先记住这个铁律:??类方法是给整个类用的工具包,实例方法是特定对象的私人订制??。举个栗子,NSString的stringWithFormat:就像餐厅的中央厨房,而initWithString:就是服务员给你端上桌的牛排。
一、从内存角度看门道
类方法最神奇的地方在于——它压根不需要对象存在!就像你还没点餐就能用餐厅的消毒湿巾。来看个内存分配对比:
- ??实例方法??:
- 必须先用alloc分配内存
- 得调用init初始化
- 用完还得操心ARC怎么处理
(是不是像网购要先注册账号?)
- ??类方法??:
- 直接[NSString string]开搞
- 内存管理自动完成
- 用完即走不墨迹
(这不就是便利店买瓶水那么简单?)
有次我徒弟写了个[[MyClass alloc] classMethod],结果编译器直接甩脸子报错。为啥?这就好比让服务员去炒菜——岗位职责搞错了啊!
二、使用场景生死局
记住这个保命口诀:??要改对象状态用实例,要搞通用功能用类方法??。比如:
- UIButton的addTarget:action:(实例方法)
- NSUserDefaults的standardUserDefaults(类方法)
- UIColor的colorWithRed:green:blue:(类方法)
去年有个哥们非用类方法操作单例对象的属性,结果引发线程安全问题。这波操作就像用餐厅的公用餐具吃自己带的泡面——不是不行,但容易出乱子啊!
三、继承体系里的猫腻
这里有个99%新手会踩的坑:??类方法不支持多态??!举个例子:
objective复制@interface Animal : NSObject + (void)eat; - (void)run; @end @interface Dog : Animal @end // 调用时 [Animal eat]; // 永远执行父类方法 [[Dog new] run]; // 会执行子类重写的方法
这就解释了为啥NSObject的description类方法和实例方法要分开实现。想不通?把它当成家族企业的传承规则就明白了——董事长职位(类方法)只能传给指定接班人,部门经理职位(实例方法)可以择优录取。
四、那些年我们犯过的二
说个真事儿:团队里有个实习生把工具类写成全实例方法,每次调用都得[[ToolClass alloc] doSomething]。结果被组长骂得狗血淋头——这相当于每次用计算器都要买台新的,你说败家不败家?
正确做法应该是:
objective复制// 工具类正确姿势 + (CGFloat)calculateDistance:(CGPoint)pointA toPoint:(CGPoint)pointB { return sqrt(pow(pointA.x - pointB.x, 2) + pow(pointA.y - pointB.y, 2)); } // 随用随调 [ToolClass calculateDistance:pointA toPoint:pointB];
小编观点
别被理论吓破胆,多写几遍自然通。下次看到类方法,就当是超市的自助结账机;碰到实例方法,就当是私人健身教练。记住,在OC的世界里,会用类方法省内存的才是真·老司机!