Objective-C中init函数实现的相关研究

今天在学习 Objective C 时见到某初始化函数中有如下代码:

self   =   [ super   init ];

if ( self ){
   
    // Initialize members
   
}
return   self ;

当时只是觉得 Objective - C C ++ 应该一样,每个子类对象都包含父类对象,所以 super self 都是指向同一对象的头部的, [ super   init ] 返回的地址应该与 self 所代表的地址一样(即 self   ==   [ super   init ] )。那么,对 self [ super   init ] 的值岂不是没有什么意义?
找朱去讨论,他也不知道是因为什么。但是他想起了在《 From   C ++   to   Objective - C 》中好像提到过这个情况,于是在一通查找之后终于在 7.1.3 P25 )找到了说明。那一节的例子中的对应代码是这样的:

if ( ! [ super   init ])

return   nil ;

// Initialize members

return   self ;

同时下面又相应的说明:

Polemic:   Most   people   use   the   instruction   self   =   [ super   init ];   if  ( self {...}   in   the   initializer .   This   is   justified   by the   fact   that   in   some   cases ,   [ super   init ]   could   return   a   different   object .   However ,   in   a   very   interesting   document   [ 6 ], Will   Shipley   shows   that   is   a   bad   practice .   It   is   far   more   logical   to   use   the   above   form ,   where   it   is   only   checked whether   [ super   init ]   returns   nil   or   not .

意思是很多人采用了 self   =   [ super   init ];   if  ( self {...} 的方法,这是由于有一些实践已经证明了 [ super   init ] 有可能返回一个(与 self 所指对象)完全不同的对象。但作者推荐了一篇文章,说这篇文章证实了这个为大多数人所使用的初始化方式是一种不好的手法。

这里所说的   a   very   interesting   document [ 6 ]   指的是:

[ 6 ]   Will      Shipley .      self   =   [ supid   init ].      http: //wilshipley.com/blog/2005/07/ self-stupid-init.html.  

是一篇博文。在这篇博文里,作者对比了两种形式的初始化方法,它们是:

1. Traditional   - init

-  ( id ) init ;
{
    if  (( self   =   [ super   init ])   ==   nil )
        return   nil ;
   
    [... initialize   my   stuff ...]     
    return   self ;
}



2. Wil ' - init

-  ( id ) init ;
{
    if  ( ! [ super   init ])
        return   nil ;
   
    [... initialize   my   stuff ...]
    return   self ;
}



作者认为不可能存在不用 self   =   [ super   init ] 就不对的情况,所以他认为第二种方法才是正确的。他曾在以前的一篇博文上说谁能找到这样的情况就给那人 20 美元。
但现在作者坦言这样的情况确实存在一个名叫 Ken   Ferry 的人编写了一个程序,该程序会自动为 Cocoa 库的每一个类派生出子类并产生程序将其实例化,并在初始化时判断 [ super   init ] 是否返回的就是 self 。最终该程序 Ken   Ferry 终于找到了一些这样的类它们都是   single   intance (单实例)的类。

说到这里大家想必也都知道是怎么回事了,单实例的类初始化函数在第一次被调用时会返回新的实例,以后再被调用则只会返回第一次生成的实例。在这种情况下,作者提出的方式 2 也就有了问题   ——若遇到父类采用单例模式,则在子类中 [ super   init ] 返回的确实非 nil ,但却也不再是子类对象所包含的那个父类对象了。如此一来子类对象所包含的那个父类对象并未被初始化,没有达到初始化函数的目的。

但是我们也应该注意到第一种方式也是不对的—— self 被重新定向为指向父类那个单实例,如此一来则发生了内存泄露,因为 self 原先所指向的对象变成了“没有链子栓着的狗”(没有指针指向它)。

原来两种方式都存在不足,那么该如何是好呢?作者提出了第三种方式:

id   superInitReturn   =   [ super   init ];

if ( ! superInitReturn  ||  self   !=   superInitReturn )
{
    return   nil ;
}

// Initialize memebers
return   self ;


我个人对此方法的理解是:若 [ super   init ] 返回的与 self 不同,则说明父类是单实例类,而单实例类的 init 函数应该是被重写过的,一般会返回 nil ,遇到这种情况我们就该收手了 , 让你的类去继承一个单实例类并非好的设计(如果想达到类似效果,请让这个单实例成为你的类的成员) , 故而返回 nil

值得一提的是该博文为作者 2005 年所作,作者于 2009 年在末尾追加了更新,指出苹果公司有些说明表明了他们很有可能要重写 [ NSObject   init ] 方法,主要是因为要采用新的内存管理手段以提高内存重用率,所以作者最终推荐的 init 方式为:

- ( id init

{
    if ( ! ( self   =   [ super   init ]))
    {
        return   nil ;
    }
   
    // Initialize members
    return   self ;
}



原文如下 :

Update   April ,   2009 :

There ' been   hints   from   Apple   that   they   might   modify   the   standard   - [ NSObject   init ]   method   to   try   to   re - use   old   object ' s memory ,   since   it   turns   out   that   a   very   common   usage   pattern   is   for   programs   to   keep   creating   and   deallocating ,   say ,   12 objects   of   the   same   class ,   over   and   over .   Re - using   the   exact   same   memory   ends   up   being   a   big   win  ( and   this   is   a   trick the   iPhone   already   does   with   its   UITableViewCell   class ,   and   that   is   a   HUGE   win   if   you   do   it   yourself   on   the   iPhone ).

So ,   from   now   on ,   I   recommend   everyone   uses:

Subclassing   NSColorPanel   the   Right   Way

-  ( id ) init ;

{
    if  ( ! ( self   =   [ super   init ]))
        return   nil ;

    // other stuff
    return   self ;
}

I   do .

我还是感到不解,看不出他的理由是什么。明天继续研究,也希望有高手能来指点一二。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
图像识别技术在病虫害检测的应用是一个快速发展的领域,它结合了计算机视觉和机器学习算法来自动识别和分类植物上的病虫害。以下是这一技术的一些关键步骤和组成部分: 1. **数据收集**:首先需要收集大量的植物图像数据,这些数据包括健康植物的图像以及受不同病虫害影响的植物图像。 2. **图像预处理**:对收集到的图像进行处理,以提高后续分析的准确性。这可能包括调整亮度、对比度、去噪、裁剪、缩放等。 3. **特征提取**:从图像提取有助于识别病虫害的特征。这些特征可能包括颜色、纹理、形状、边缘等。 4. **模型训练**:使用机器学习算法(如支持向量机、随机森林、卷积神经网络等)来训练模型。训练过程,算法会学习如何根据提取的特征来识别不同的病虫害。 5. **模型验证和测试**:在独立的测试集上验证模型的性能,以确保其准确性和泛化能力。 6. **部署和应用**:将训练好的模型部署到实际的病虫害检测系统,可以是移动应用、网页服务或集成到智能农业设备。 7. **实时监测**:在实际应用,系统可以实时接收植物图像,并快速给出病虫害的检测结果。 8. **持续学习**:随着时间的推移,系统可以不断学习新的病虫害样本,以提高其识别能力。 9. **用户界面**:为了方便用户使用,通常会有一个用户友好的界面,显示检测结果,并提供进一步的指导或建议。 这项技术的优势在于它可以快速、准确地识别出病虫害,甚至在早期阶段就能发现问题,从而及时采取措施。此外,它还可以减少对化学农药的依赖,支持可持续农业发展。随着技术的不断进步,图像识别在病虫害检测的应用将越来越广泛。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值