Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 当可以从实例外部设置IVAR/属性时,为什么要创建自定义init?_Objective C_Variables_Inheritance_Methods_Init - Fatal编程技术网

Objective c 当可以从实例外部设置IVAR/属性时,为什么要创建自定义init?

Objective c 当可以从实例外部设置IVAR/属性时,为什么要创建自定义init?,objective-c,variables,inheritance,methods,init,Objective C,Variables,Inheritance,Methods,Init,我正在读一本Objective-C的书,我有一个问题,这本书似乎没有真正回答 假设我有两个定制的类 第一个类称为ClassA。它当然有.h和.m文件。第二个类称为ClassB。它也有.h和.m文件 在代码的某个地方,“ClassA”有以下方法: -(IBAction)displaySomeText:(id)sender { ClassB *myNumber = [[ClassB alloc]init]; NSString *numberString = [myNumber s

我正在读一本Objective-C的书,我有一个问题,这本书似乎没有真正回答

假设我有两个定制的类

第一个类称为
ClassA
。它当然有.h和.m文件。第二个类称为
ClassB
。它也有.h和.m文件

在代码的某个地方,“ClassA”有以下方法:

-(IBAction)displaySomeText:(id)sender {
    ClassB *myNumber = [[ClassB  alloc]init];

    NSString *numberString = [myNumber storedNumberAsString];
    // storedNumberAsString is just a method that returns a string object that holds
    // myVariable.

    [textView insertText:numberString];
    //textView is a object  I created that just displays some text on screen.

    [myNumber release];
}
这本书告诉我
ClassB
应该有一个方法:

-(id)init {
    [super init]; //I know why this is done, the book explains it well.
    myVariable = 42; // I created this variable already in the ClassB .h file 
    return self;
}
现在,当我在Interface Builder中单击我连接的按钮等时,显示的数字是
42

我的问题是,如果我可以在
ClassA
的方法中执行以下操作,为什么我必须为
ClassB
创建
-(id)init
方法:

-(IBAction)displaySomeText:(id)sender {
    ClassB *myNumber = [[ClassB alloc]init];
    myNumber.myVariable = 42; //I just do this to skip the -(id)init method.

    NSString *numberString = [myNumber storedNumberAsString];
    [textView insertText:numberString];
    [myNumber release]; 
}

执行此操作时,它仍然显示相同的值:
42
。我可以把它换成我喜欢的任何东西。那么,为什么不直接使用继承自
NSObject
init
,并使用简单的方法
myNumber.myVariable=42

假设实例变量的值比整数更复杂。假设它涉及从文件中读取字符串,或者通过网络获取一些信息,或者只是做一些算术运算。在这种情况下,让
ClassA
负责正确设置该值是没有意义的。这将打破一开始让单独的类变得有用的规则

在这个非常简单的例子中,您是对的,可能没有理由为
ClassB
使用自定义初始值设定项,但一般来说,类本身应该负责正确设置其状态。将责任强加给其他类意味着其他类需要了解第一类的内部,这意味着这两个类之间的耦合可能过于紧密


在某些情况下,ivar的值可能是一条只有
ClassA
知道的信息,或者需要基于此类信息进行计算。然后,您应该为接收该值的
ClassB
创建自定义初始值设定项,例如,
-(id)initWithInteger:
这将成为,然后您将覆盖
-[ClassB init]
以合理的默认值调用它。

假设实例变量的值比整数更复杂。假设它涉及从文件中读取字符串,或者通过网络获取一些信息,或者只是做一些算术运算。在这种情况下,让
ClassA
负责正确设置该值是没有意义的。这将打破一开始让单独的类变得有用的规则

在这个非常简单的例子中,您是对的,可能没有理由为
ClassB
使用自定义初始值设定项,但一般来说,类本身应该负责正确设置其状态。将责任强加给其他类意味着其他类需要了解第一类的内部,这意味着这两个类之间的耦合可能过于紧密


在某些情况下,ivar的值可能是一条只有
ClassA
知道的信息,或者需要基于此类信息进行计算。然后,您应该为
ClassB
创建一个自定义初始值设定项,该初始值设定项接收该值,例如,
-(id)initWithInteger:
这将成为,然后您将覆盖
-[ClassB init]
以使用一些合理的默认值调用它。

如果ClassB实例不需要初始化任何内容(除了nil/zero之外),您不需要为ClassB创建显式的
init
方法。在这种情况下,问题是将
myVariable
设置为
42
是否是ClassB的,或者
myVariable
是否只是ClassB中可以设置为任何值的字段


也就是说,问题是概念性的,而不是物理意义上的。如果值
42
“在概念上属于”ClassB,那么ClassB应该有一个
init
方法来设置它。如果该特定值对ClassA的意义大于对ClassB的意义,那么ClassA的某个方法应该设置它。如果您这样做“错误”代码仍然可以很好地工作,但是您的设计稍微不那么优雅,稍微不那么可扩展,稍微不那么健壮。

如果ClassB的实例不需要初始化任何东西(除了nil/zero),您不需要为ClassB创建显式的
init
方法。在这种情况下,问题是将
myVariable
设置为
42
是否是ClassB的,或者
myVariable
是否只是ClassB中可以设置为任何值的字段


也就是说,问题是概念性的,而不是物理意义上的。如果值
42
“在概念上属于”ClassB,那么ClassB应该有一个
init
方法来设置它。如果该特定值对ClassA的意义大于对ClassB的意义,那么ClassA的某个方法应该设置它。如果您这样做“错误”代码仍然可以很好地工作,但是您的设计稍微不那么优雅,稍微不那么可扩展,稍微不那么健壮。

这是一个棘手的问题。我是在构造师(初始值设定者)之后“长大”才想到这一点的运行时,对象应该准备就绪。您应该能够安全地调用它上的任何方法。因此,您需要在构造函数中设置0不是有效值的任何实例变量。我喜欢在它们有0值时设置它们,只是为了保持理智,因为我永远不想知道我所使用的每种语言的详细信息k,比如它们是否自动将实例变量初始化为0

但是,有些参数不支持初始化某些变量

  • 初始化很复杂,例如加载文件或从网络获取数据。是否要保留