Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to initialize an object?

I've been using Objective-C for a few years, but I'm still unsure how to initialize an object. Our problem is this:

-(id)init {
    self = [super init];
    if (self) {
        self.backgroundColor = [UIColor blueColor];
        self.textColor = [UIColor greenColor];
    }
    return self;
}

-(id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor yellowColor];
    }
    return self;
}

Getting it to be initialized the same in both methods means either copy and paste coding (huge no-no, causes endless problems due to human error, such as values being different, like in the example above) or a new method:

-(id)init {
    self = [super init];
    if (self) {
        [self initialSetup];
    }
    return self;
}

-(id)initialSetup {
    self.backgroundColor = [UIColor blueColor];
    self.textColor = [UIColor greenColor];
}

This then has the problem that if a subclass has an initialSetup method, the superclass calling [self initialSetup] will call the subclass's initialSetup, and thus ignore all of the superclass's setup. You can get around this by appending the class name each time, such as initialSetupTextField.

This seems rather messy though. This is all just to initialize an object. How does everyone else do this?

like image 623
Andrew Avatar asked Aug 12 '13 16:08

Andrew


People also ask

How can we initialize an object in Java?

Instantiation: The new keyword is a Java operator that creates the object. Initialization: The new operator is followed by a call to a constructor, which initializes the new object.

How do you initialize an object in class?

There are two ways to initialize a class object: Using a parenthesized expression list. The compiler calls the constructor of the class using this list as the constructor's argument list. Using a single initialization value and the = operator.

What is used for initializing new objects?

A constructor is a special method that has the same name as the class and is used to initialize attributes of a new object.


3 Answers

Every class should have a designated initializer; the one true init... method variant that must always be called to properly initialize the class (as Matt states).

However, that doesn't fully solve the problem in that a class may also support instantiation through unarchival, which runs into the same "where do I put the common initialization goop" problem in your question.

Typically, I create a method like:

- (void)commonInit
{
     ... common initialization goop goes here ...
}

And then call it first from the designated initializers and/or initWithCoder:.

Yes, a bit messy, but not much you can do about it.

A general strategy to reduce the mess:

• provide very very few initializers; maybe init + one initializer with all the possible arguments for other configurations.

• Designate the super's initializer as your DI and make any additional initializers call through it. When subclassing where you have a more specific DI (see UIView's initWithFrame:), override the super's DI to call [self initFancy:...] which then calls [super initThroughSupersDI].

like image 127
bbum Avatar answered Sep 25 '22 06:09

bbum


You're missing the concept of a Designated Initializer. You write one init method that does the heavy lifting. All other initializers just call the designated initializer. Your example would look like:

-(id)init {
    return [self initWithFrame:CGRectZero];
}

-(id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor yellowColor];
    }
    return self;
}
like image 25
Matt Wilding Avatar answered Sep 23 '22 06:09

Matt Wilding


…appending the class name each time, such as -initialSetupTextField

Yes, exactly that, or you can create a C function for your private instance initialization routine -- when the designated initializer is insufficient. I use a different naming scheme from yours, but as long as you use a convention which avoids collision, then you're good. I'm mentioning that because the method in your example could be confused for a getter.

Another thing I do is return a value from this routine which indicates whether there was an error (i.e. nil should be returned).

like image 41
justin Avatar answered Sep 25 '22 06:09

justin