• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: modifying self in init
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: modifying self in init


  • Subject: Re: modifying self in init
  • From: Ben Golding <email@hidden>
  • Date: Thu, 16 Sep 2004 16:41:06 +1000


On 15/09/2004, at 16:08, Mike Bolton wrote:

I'm wondering if anyone can help me with the following
problem:

I have a superclass, A, and a subclass, B.  I've
created a special init routine for class A, called
initWithPath, which sets a few of the ivars of the
superclass, such as the fileName, etc.  Now, there are
two (or more) different types of files that may be
passed to the init routine, but the file type cannot
be determined until the header for the file has been
read.  Anyways, if the file is of type 1, I want the
initWithPath routine of A to set the ivars as usual,
and return an object of type A (in this case, simply
return self).  Now, if the file is of type 2, I want
the ivars in the superclass to be set to the same
values, but an object of type B should be returned.

One way I thought of accomplishing this is to do
something like this:

@implementation A

- (id) initWithPath:(NSString *)path
{
  if (self = [super init])
  {
     //read header of file
     if (fileType == 2)
     {
          [self release];
          self = [[B alloc] init];  //maybe I need a
retain here?
     }

     [self setFilename:path];
     ivar1 = blah;
     ivar2 = bleh;
     etc.
  }
   return self;
}

@end

this seems to work, although I'm not sure if modifying
what self points to is a good idea.  The other
solution would be to have something like:

@implementation A
 - (id) initWith...
{
  id object = self;

  if (object = [super init])
  {
        blah blah
        if (fileType == 2)
        {
            [self release];
            object = [[B alloc] init];
        }
     [object setFilename:path];
     [object setIvar1:blah];
     [object setIvar2:bleh];
  }

return object;
}

the problem with the second implementation is that I
need to create setter methods for each ivar I want to
assign values to (not a big deal, but the first
implementation was able to avoid this).  Although a
solution to this would be to create another method
which is responsible for setting the default values of
the objects, although this is normally what the init
routine is responsible for.

Anyways, if anyone can give me any advice or
suggestions on how to properly implement this, I would
greatly appreciate it.  I've searched the list
archives for similar problems, but I didn't find any
messages which addressed modifying the value of self.

I read the responses to this and thought I'd suggest a different way of doing this. What I'd do is to make a factory class that takes a file passed to it, inspects the file's type, and then returns an instance of the appropriate class to read that file's type. To me, determining which class manipulates a file is a separate problem from actually manipulating the file and they should be in separate classes.


	@implementation FileReaderFactory
	+ (FileReader *)fileReaderForPath:(NSString *)path
	{
		blah blah;
		if (fileType == 2)
			return [[[B alloc] initWithPath:path] autorelease];
		else
			return [[[A alloc] initWithPath:path] autorelease];
	}
	@end

	@implementation FileReader
	- (id)initWithPath:(NSString *)path
	{
		if ((self = [super init]) == nil)
			return nil;

		[self setFilename:path];
		[self setIvar1:blah];
		[self setIvar2:bleh];

		return self;
	}

@implementation A : FileReader // bastardised Objective C but anyway ...
- (id)initWithPath:(NSString *)path
{
if ((self = [super init]) == nil)
return nil;
// special stuff for A
return self;
}
@end


@implementation B : FileReader // bastardised Objective C but anyway ...
{
if ((self = [super init]) == nil)
return nil;
// special stuff for B
return self;
}
@end


It gives you a nice way to replicate methods in a common subclass but also gives you a way to specialise the classes that read the file.

You would use it like:

	fileReader = [FileReaderFactory fileReaderForFile:path];

If performance is a particular issue (ie, you're worried about opening the file twice (probably not much of a real concern because you can rely on the kernel doing some caching of open files)), you could pass an NSData with the file's contents to the FileReader's subclass's constructor.

Anyway, that's how I'd do it which would avoid having to fiddle with reassigning to self altogether.

	Ben.

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: modifying self in init
      • From: Ondra Cada <email@hidden>
    • Re: modifying self in init
      • From: Ben Golding <email@hidden>
References: 
 >modifying self in init (From: Mike Bolton <email@hidden>)

  • Prev by Date: Creating popup button's menu at the last moment
  • Next by Date: Re: build numbers
  • Previous by thread: Re: implementing dataWithContentsOfMemory as NSData category
  • Next by thread: Re: modifying self in init
  • Index(es):
    • Date
    • Thread