OC为何很少new一个对象?

2021-03-05  本文已影响0人  Invisible_He
image.png

前言

对于OC,我们最常用的生成一个对象的方式是下面这样的

NSObject *obj = [[NSObject alloc] init];

当然也会有下面这种方式

NSObject *obj = [NSObject new];

但是这种方式是很少用的。对于大部分人的理解,其实new的效果和结果是和alloc组合init是一样的,那么既然如此,为何大家均选择了调用两个方法的稍微复杂点的方式,而并没选择调用一个方法new的简单方式呢?

OC为何很少new一个对象?

苹果官方解释

下面是苹果官方文档

Type Method

# new

Allocates a new instance of the receiving class, sends it an [init] 
message, and returns the initialized object.

Framework

*   Objective-C Runtime

## Declaration

+ (instancetype)new;

## Return Value

A new instance of the receiver.

## Discussion

This method is a combination of [alloc] and [init]. Like [alloc], it 
initializes the `isa` instance variable of the new object so it points to 
the class data structure. It then invokes the [init] method to complete 
the initialization process.

关键则是后面的两句

Allocates a new instance of the receiving class, sends it an [init] 
message, and returns the initialized object.
//生成一个新的实例对象,并发送一个[init]方法,然后返回初始化过的对象
This method is a combination of [alloc] and [init]. Like [alloc], it 
initializes the `isa` instance variable of the new object so it points to 
the class data structure. It then invokes the [init] method to complete 
the initialization process.
//[new]方法是后面两个方法的结合,也就是:[alloc]和[init].  [alloc]:
初始化一个新对象的isa实例变量,并且指向其对应的类数据结构。然后调用[init]方法去完成初始化过程

从解释可以看出,[new]方法是后面两个方法的结合,也就是:[alloc]和[init]。并且作用也是和这两个方法是一样的。从权威的官方文档解释,我们仍然看不出两者之间的区别。

GNUstep解释

偶然间,我在另一个权威的代码文档中发现了他们之间的不同点,那就是GNUstep。GNUstep是GNU对OC的开源,可以说是除苹果外,对于OC最权威以及正确的一份代码资料了。下面则是GNUstep对于new的解释

/**
 *   This method is a short-hand for alloc followed by init, that is,
 *    NSObject *object = [NSObject new];

 * is exactly the same as
 *    NSObject *object = [[NSObject alloc] init];

 *   This is a general convention: all <code>new...</code>
 *   methods are supposed to return a newly allocated and
 *   initialized instance, as would be generated by an
 *   <code>alloc</code> method followed by a corresponding
 *   <code>init...</code> method.  Please note that if you are
 *   not using a garbage collector, this means that instances
 *   generated by the <code>new...</code> methods are not
 *   autoreleased, that is, you are responsible for releasing
 *   (autoreleasing) the instances yourself.  So when you use
 *   <code>new</code> you typically do something like:

 *      NSMutableArray *array = AUTORELEASE ([NSMutableArray new]);

 *   You do not normally need to override <code>new</code> in
 *   subclasses, because if you override <code>init</code> (and
 *   optionally <code>allocWithZone:</code> if you really
 *   need), <code>new</code> will automatically use your
 *   subclass methods.

 *   You might need instead to define new <code>new...</code>
 *   methods specific to your subclass to match any
 *   <code>init...</code> specific to your subclass.  For
 *   example, if your subclass defines an instance method

 *   initWithName:

 *   it might be handy for you to have a class method

 *    newWithName:

 *   which combines <code>alloc</code> and
 *   <code>initWithName:</code>.  You would implement it as follows:


 *     + (id) newWithName: (NSString *)aName
 *     {
 *       return [[self alloc] initWithName: aName];
 *     }
 */
+ (id) new
{
  return [[self alloc] init];
}

我给大家找出了关键点,如下

 *   Please note that if you are
 *   not using a garbage collector, this means that instances
 *   generated by the <code>new...</code> methods are not
 *   autoreleased, that is, you are responsible for releasing
 *   (autoreleasing) the instances yourself.  So when you use
 *   <code>new</code> you typically do something like:

 *      NSMutableArray *array = AUTORELEASE ([NSMutableArray new]);

这句话的意思很明显了,就是说,如果你没使用垃圾回收(这里的意思是指,ARC,因为OC一直是一门具有垃圾回收机制的一门语言)的话,也就是在MRC下,使用new生成的实例对象,将不会自动释放,将由你手动管理对象的release。
其实我理解这句话的意思就是,如果在MRC下,使用new的时候,写代码的话,主要就得写成下面这样:

NSMutableArray *array = AUTORELEASE ([NSMutableArray new]);

这样的写法也是和普通的写法有很大不同的,之后现在在来看看这个AUTORELEASE


image.png

从图中可以看到:AUTORELEASE函数的这种隐式声明早已经在c99就不合法了。

最终解释

OC是一门上世纪八十年代就诞生的一门语言,但是ARC则是Xcode4开始才支持的,而Xcode4则是在2011年才发布的。也就是说,在长达接近三十年的时间里,OC都是在MRC下编写代码的,从上面GNU文档里的解释可以看出:
1、在MRC下,new的对象release方式的不同点,因此大家就选择了相对复杂的[alloc]和[init]的组合方式,并在长达三十年的代码风格中形成了风俗和习惯,并衍生至今。
2、当然,如果用new生成一个对象的话,那么初始化方法就只能调用到init,而不能调用到自定义的initWith等方法,然而我们实际开发中,却常自定义init方法,因此new就在此种情况下不太合适

image.png image.png

从上面文档解释也能知道的一点是:在如今的ARC下,其实[new]和[[alloc] init]是没什么区别的,从官方文档的解释和GNU源码也能看得出来,他两是一样的。

上一篇下一篇

猜你喜欢

热点阅读