2014-01-26 176 views
-1

我要检查,如果一个子类的以下实现是正确的目标C.超类初始化

首先代码父父写的Objective C的子类:

#import "Employee.h" 

    @implementation Employee 

    -(id)init 
    { 
    return [self initEmployee:(NSString *)@"" withId:(NSString *)0]; 
    } 

    -(id)initEmployee:(NSString *)theName withId:(NSString *)theId 
    { 
     self = [super init]; 
     if (self) { 
      _name = theName; 
      _EmpId = theId; 
     } 
     return self; 
    } 

    @end 

然后子类。

#import "FullTimeEmp.h" 

@implementation FullTimeEmp 

-(id)init 
{ 
    return [self initEmployee:(NSString *)@"" 
         withId:(NSString *)@"" 
        andSalary:(NSNumber *)0 
        withBonus:(NSNumber *)0]; 
} 

-(id)initEmployee:(NSString *)theName 
      withId:(NSString *)theId 
     andSalary:(NSNumber *)theSalary 
     withBonus:(NSNumber *)theBonus 
{ 
    self = [super initEmployee:(NSString *)theName withId:(NSString *)theId]; 
    if (self) { 
     self.salary = theSalary; 
     self.bonus = theBonus; 
    } 
    return self; 
} 

@end 

这运行正常,但我一直没能确认这是做了正确的方式,使用:

自我= [超级initEmployee:(的NSString *)theName withId:(的NSString * )theId];

在继承超类部分(Name和ID),然后是子类部分的子类中,指定组成Full Time Employee对象的子类添加(Salary和Bonus)。

我读过所有关于我们使用自己的理由= [超级初始化],但已很难找到如何在子类的初始化是在我的书我还是在网上编码很好的例子。

+3

**为什么**哦,为什么所有这些多余的,丑陋的,不可读的,不正确的演员? :((((( – 2014-01-26 21:15:33

+1

请阅读[* Cocoa的编码指南:命名方法*](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html)。Better名字是'initWithName:employeeId:'和'initWithName:employeeId:salary:bonus:'。 –

回答

0

你有正确的想法尽可能初始化去。你基本上只需要以某种方式正确地初始化超类。你不做到这一点正是这样在您的子类,基本上是与一些其他成员的超类,但在这种情况下,它似乎是适当的。你可能有一个子类,其中,例如,theId或其他一些领域将永远是该子类,在这种情况下,你不需要为它传递一个值的子类的初始化值相同。只要你以最适合你的情况的方式初始化超类,你应该是好的。

但是,你似乎是混乱的方法签名和方法调用,或发送消息的语法。这:

self = [super initEmployee:(NSString *)theName withId:(NSString *)theId]; 

和类似的应该只是这样的:

self = [super initEmployee:theName withId:theId]; 

当你定义一个方法,你需要这些东西(NSString *)告诉编译器是什么类型的每一个你的论点是,但是当你正在调用方法/发送一个消息,你已经有一个已经有一个已知类型的参数的对象,所以你不需要它。你实际上完成这里是铸造NSString *NSString *,这显然是多余的。

编辑:由于格热戈日提到,一般最好是直接通过自己的实例变量访问你的初始化方法的性能,即代替:

self.salary = theSalary; 

,而不是做:

_salary = theSalary; 

假设你还没有用不同的名字来合成它。一个很好的理由是因为子类可以重写属性的setter方法,这可能会导致非常不可预测的行为。通常,在部分构建状态下发送消息到self应避免,因为这样做会产生副作用。显然,如果你设置一个由超类定义的属性,并且你没有访问实例变量的权限,或者你正在使用延迟初始化,那么除了使用setter外没有其他选择在这里初始化它),但这不是你在这个例子中的。

编辑2:另外,跟这个有几点:

-(id)init 
{ 
    return [self initEmployee:(NSString *)@"" 
         withId:(NSString *)@"" 
        andSalary:(NSNumber *)0 
        withBonus:(NSNumber *)0]; 
} 

首先,你不必觉得有必要提供直init方法,如果它没有任何意义,以对这些默认值的东西。如果你确定有一个没有姓名和ID的雇员,那么很好,但如果你只用实际的数据初始化你的一个班级是有意义的,那么不要为没有重写init甚至关于如果你真的想阻止人们使用它,就会抛出异常。

其次,NSNumber是一个对象,所以当你尝试直0分配给它,它是相当于指针设置为nil,而不是创建一个对象可言,这可能不是你想要的这里。要真正零值创建NSNumber S,你想使用你的NSString做同样的方式文字,像这样(这里也去掉石膏):

-(id)init 
{ 
    return [self initEmployee:@"" 
         withId:@"" 
        andSalary:@0 
        withBonus:@0]; 
} 

或只使用常规int代替NSNumber如果你不需要它们是对象。

+0

添加一条关于不使用self和直接_var的注释 - 它可能导致不保留参数 - 我相信他现在知道那 –

+0

@GrzegorzKrukowski:我添加了一个注释,好点:) –

+0

感谢@PaulGriffiths&GrzegorzKrukowski对我的编码做出了非常全面的回应,现在我已经很好地解释清楚了,正如我之前提到的,我发现很难找到一些具体的例子如何正确使用。 – irishetcher

0

作为更新我在OP的问题,并帮助其他人谁可能这里有同样的困惑是我的代码重新雷农按所给的建议是:

#import "Employee.h" 

@implementation Employee 

-(id)initEmployee:(NSString *)theName withId:(NSString *)theId 
{ 
    self = [super init]; 
    if (self) { 
    _name = theName; 
    _EmpId = theId; 
    } 
return self; 
} 

@end 

而且

#import "FullTimeEmp.h" 

@implementation FullTimeEmp 

-(id)initEmployee:(NSString *)theName 
      withId:(NSString *)theId 
     andSalary:(NSNumber *)theSalary 
     withBonus:(NSNumber *)theBonus 
{ 
    self = [super initEmployee:theName withId:theId]; 
    if (self) { 
     _salary = theSalary; 
     _bonus = theBonus; 
    } 
return self; 
} 

-(NSNumber *)calcPay 
{ 
    NSNumber *pay; 
    pay = [NSNumber numberWithFloat:([self.salary floatValue] + [self.bonus floatValue])]; 
    return pay; 
} 


@end