How to create instances when wrapping procedural code into OOP? - objective-c

I’d like to wrap a procedural event C API into Objective-C. The procedural API revolves around some opaque pointer, say EventRef. There are several kinds of events that can be represented by this type – mouse events, keyboard events, etc. You can get the kind of the event by calling some function, say EventGetType(event).
It seems very natural to represent the different event kinds by different classes. In other words, have an Event class and subclasses like MouseEvent or KeyboardEvent. My question is how to create instances given some EventRef?
I can’t simply have a public initializer that takes the EventRef, as the callers would have to find the correct class before initializing. This feels clumsy:
EventType type = EventGetType(event);
switch (type) {
case EventTypeMouse:
…[[MouseEvent alloc] initWithEvent:event]…
case EventTypeKeyboard:
…[[KeyboardEvent alloc] initWithEvent:event]…
I could do some magic in the Event initializer so that it would pick the right class for the called:
#implementation Event
- (id) initWithEvent: (EventRef) event {
// pick correct subclass, initialize and return that
}
One of the downsides is that this makes subclassing the event types harder. And I don’t like the magic in the initializer. I could also write some kind of registry, but that already feels too complex. How would you go about this? (Please note that the event API is just an example to have something more concrete to reason about.)

The scheme you describe with your magic initializer is a factory pattern. I think it's indeed that way to go, however I wouldn't do it that way but rather:
#interface EventFactory
- (id) eventForEventRef:(EventRef)event;
#end
That is, move the factory to its own class. That way you don't have to mess with the superclass once you add a new subclass.

Related

Best practice style -- method names with delegates and ownership

Is it a good practice or a bad practice to have same-named methods across classes, particularly where inheritance and/or protocols are involved?
For example, I have a protocol of some kind:
#protocol DataReceiver <NSObject>
- (void)handleNewData:(id)data;
#end
And I have a controller class that owns some stuff, such as
#interface OwnerOfAllThings <DataReceiver>
//this child does NOT conform to DataReceiver
#property (nonatomic, strong) SomeOwnedModel myChild;
#end
But the child is opaque, so my implementation of -handleNewData: is basically just a pass-through and calls a method in the child that takes care of the actual handling. So my question is, although it's not functionally so different, is it a bad idea to put an identically named method in SomeOwnedModel, being that it might be confused with the declaration in the protocol? Or should it in fact be exactly the same, for consistency?
i.e., which is better (assuming that the SomeOwnedModel.h declares the appropriate method):
#implementation OwnerOfAllThings
- (void)handleNewData:(id)data {
//Option 1:
[self.myChild handleNewData:data]; //OR...
//Option 2:
[self.myChild ownerReceivedNewData:data]; //or whatever else
}
#end
Since OwnerOfAllThings is simply invoking the method in the child, I might be inclined to keep the same method names, possibly even have SomeOwnedModel conform to the same protocol. If you use the "use unique names" pattern, I can only imagine how unwieldy it would become if you had three or four levels of classes or if you had a ton of methods in your protocol, being forced to come up with arbitrarily unique names for each.
By way of example, I have NSOperation based framework for NSURLSession, with a session manager object (a wrapper for NSURLSession), and a bunch of individual NSOperation classes (one for download tasks, one for data tasks, etc.). In this case, while NSURLSession conforms to not only NSURLSessionDelegate, it also conforms to NSURLSessionTaskDelegate, NSURLSessionDataDelegate, etc. (because that's how NSURLSession works). But when this session manager receives one of these task-related delegate calls, it simply routes the event to the appropriate operation object. So to make this clear, I made the various operation objects conform to the appropriate protocol (e.g. download operation conforms to NSURLSessionDownloadDelegate, data operation conforms to NSURLSessionDataDelegate, etc.). The end result is that despite a dizzying collection of classes and protocols, the intent is unambiguous.
So, bottom line, if the parent is simply routing the event to the appropriate child and offering no material contribution beyond that, I'd be inclined to use same methods (and possibly same protocol). But if the parent class is offering something substantively richer/different, functionally, over what the child is performing, then a unique name would probably be appropriate.
As an aside, when coming up with your method names, I might suggest a method name that distinguishes "I received a bit of data and more may be coming" (i.e. didReceive...) vs. "I received all of the data" (i.e. didComplete...). This is an informal convention Apple uses in NSURLConnection and NSURLSession, and following it might be helpful to make your intent clear.
The best way to name a method is always to try to accurately describe (beware of excessive verbosity) what the method does. If both your methods do exactly the same it's probably a good idea to extract that functionality to a self-contained class.
Often the convention is followed in iOS to name delegate methods like the one you have shown in the following form:
-(void)dataSource:(DataSource*)dataSource didReceiveNewData:(id)data {
//Call your "child" object here
[self.myChild doAWithData:data];
}
Where dataSource is the object that calls the delegate method.
In my opinion you're running into this problem because you're not accurately describing what the method actually does by using "handle" data.
Perhaps a good source for standards is Apple's documentation.

How should I be using class variables in Objective-C?

This has been bugging me for a long time, and I have tried to look it up many times.
When I first began learning Objective-C, I remember looking into class variables. I saw many threads on stack overflow and elsewhere that basically said, "Objective-C doesn't support class variables like C does, but there are some workarounds."
Reading this made me shy away from using class variables, especially because I have read hundreds of times that global variables tarnish the elegance of OOP.
So I have a very open ended, opinionated, and conversational question:
Should I use class variables in objective C? Also, am I doing it right?
Here is my situation: I am making an app, and I set up a touch handling class to deal with all the input received from screen touches. The data is pretty useful, and I would like every single sprite to have access to it.
Since every object is a subclass of my GameObject class, I figure I just make a class variable, done like so:
header for GameObject class:
+(SSTouchHandler *)touchHandler;
+(void)setHandler:(SSTouchHandler *)handler;
implementation for GameObject class:
static SSTouchHandler *touchHandler = nil;
+(SSTouchHandler *)touchHandler
{
if (touchHandler)
return touchHandler;
else
return nil;
}
+(void)setHandler:(SSTouchHandler *)handler
{
touchHandler = handler;
}
Now, this works. This works beautifully.
I can refer to my handler with [GameObject touchHandler] from every place I need.
This is all I could ever want and more.
But should I use this method? Am I dirtying the beauty that is object oriented programming?
Is there a way I should touch up this process to make it work optimally?
Thanks for any and all input, I probably rambled a bit, I just don't want to proceed with a faulty game structure.
I saw many threads on stack overflow and elsewhere that basically
said, "Objective-C doesn't support class variables like C does, but
there are some workarounds.
"Class variables" make no sense in the context of C since C is not object oriented.
So I have a very open ended, opinionated, and conversational question:
Should I use class variables in objective C? Also, am I doing it
right?
This is more of a general OOP question than anything specific to Objective-C. The answer tends to be pretty subjective, but in general I'd say to avoid them unless you're trying to set a property of some sort that affects all instances of a class.
Here is my situation: I am making an app, and I set up a touch
handling class to deal with all the input received from screen
touches. The data is pretty useful, and I would like every single
sprite to have access to it.
It sounds to me like a better design pattern for this would be to pass the SSTouchHandler instance as a parameter to the initializer of the sprite objects that use it. e.g.:
#interface GameObject : NSObject
- (id)initWithTouchHandler:(SSTouchHandler *)handler;
#end
Now, if you really want to use the same instance of SSTouchHandler for every GameObject, you have two options:
1) The controller/factory that creates the GameObject objects should create and keep a reference to a single instance of SSTouchHandler, and then initialize any new GameObject instances with it. For example:
#interface GameObjectController : NSObject
#property (nonatomic, strong, readonly) SSTouchHandler *touchHandler;
- (GameObject *)newGameObject;
#end
#implementation
- (id)init
{
if ((self = [super init])) {
_touchHandler = [[SSTouchHandler alloc] init];
}
return self;
}
- (GameObject *)newGameObject
{
return [[GameObject alloc] initWithTouchHandler:self.touchHandler];
}
#end
2) You could make SSTouchHandler a shared singleton and call methods on the shared instance directly from the implementation of GameObject. However, shared singletons are discouraged in OOP because they hide dependencies and make it difficult to unit test code that depends on them. You shouldn't go down this route unless you deem it absolutely necessary.
implementation for GameObject class: ...
If you decide that the patterns above aren't suitable for your use case (and that sometimes does happen), yes that is essentially how you would implement class properties in Objective-C. One thing:
if (touchHandler)
return touchHandler;
else
return nil;
This is not necessary, you can just return touchHandler since it will be nil anyways if not set.
If it works, you're done. I think there are some improvements, though. First, you might like to use an instance var here: it's not more complicated, but it allows some flexibility in the future (e.g. if you want to make two views side by side). Also, using a bare pointer is not so good; the class here does not own the pointer, and it can be left dangling! Defining the touchHandler as a property (also an instance var) takes care of that problem.

Objective-c Calling subclasses by baseclass

I have an attack method I am trying to implement in class 'Enemy', in which it will call upon the subclasses of the class 'Paragon'.
The subclasses are created via #interface in the .h file, and implemented in .m.
This is my current attack method in stated in the Enemy class:
-(void)chosenParagonForAttack:(Paragon*)paragon{
_paragonLink = nil; //_paragonLink, is an object of class Paragon.
_paragonLink = paragon;
[self attackParagon];
[paragon underAttackByEnemy :self];
}
The problem I am getting is that since the actual paragon is created by a subclass, the attack is not occuring. The subclasses define a different "paragon", with differing images and data etc.
Is there a way to call the subclasses just stating the baseclass (Paragon)?
I can work around this by creating an if statement containing every subclass of the Paragon class, however I am interested to find out if there is a better way to go about this.
I was thinking that 'isSubclassOfClass' or 'isKindOfClass' would sort it out but I haven't been successful using them.
Thanks.
This sounds like a general object-oriented design problem, rather than something that's specific to Objective-C.
You shouldn't use a series of if statements that are aware of every Paragon class. Doing so would mean that your Enemy class is tightly-coupled to every Paragon subclass: if you ever wanted to add a new Paragon subclass, you'd also have to update Enemy.
Instead, each of your Paragon subclasses should override the underAttackByEnemy: method and probably any methods on Paragon that are called from attackParagon. That way, your sub-classes will know that the attack is occurring and can perform any logic that's specific to them while allowing Enemy to only know about Paragon, rather than all of Paragon's sub-classes. Any attack logic that's common among all the Paragon sub-classes should be implemented in Paragon and then called from the sub-classes: for example, [super underAttackByEnemy:enemy]

Sending messages to objects?

I have done this successfully many times before, but this time it just won't work.
The code in my .h file:
#interface Images : NSView {
}
- (void) draw;
#end
The .m file (of another object):
- (IBAction) go: (id) sender; {
[Images draw:nil];
}
When I try to compile this, it says the following:
'*' may not respond to '*
Images may not respond to '+draw'
This has me quite confused. Shouldn't this be working?
Please Note: Yes, I have seen the other questions about messages, but none of those answers was even partially helpful for me. After reading them, I was even more confused.
Your draw method is an instance method: it can only be called on instances of the Images class. In your go: method you're trying to call it as a class method—if this is what you want, change it to:
#interface Images : NSView
+ (void)draw;
#end
I think a review of some of the basic concepts of object-oriented programming is in order; namely the difference between a class and an object or instance.
A class, in the general sense, is a collection of data and the functions which act upon it. A class defines the interface that one uses to access and manipulate data that is logically grouped together, and serves as a blueprint for creating objects or instances. See http://en.wikipedia.org/wiki/Class_(computer_programming)
Instances of a class (objects) are the typical things you manipulate in an object-oriented program, and they are created from the class "blueprint" and follow the behavior as specified by the class.
A typical example would be a fruit- take apples for example. An imaginary Apple class would represent all apples in the general sense and would model properties such as color and size and actions such as wash and eat. An instance would represent one, single physical apple- a Granny Smith or Pippin or whatever variety.
Just as it doesn't make sense to wash or eat apples in the general sense of the word (the concept of apples, not the agglomeration), typically it doesn't make sense to tell a class what to do. You tell objects (individual apples) what to do.
The code you present above defines the class Images. The "-" in front of -(void)draw indicates that the draw method only exists for specific objects. It is an instance method in typical OO parlance.
Of course, in Obj-C it is also possible to send a message to a class without requiring an object. This is denoted by a "+" in front of the method name, as other answers indicate. This is called a static method and it typically used to control some shared behavior or aspect of all objects of that particular class.
The problem with your code is that you are declaring -(void)draw as an instance method but calling it as a static method. Which way you want to do things is up to you, and it's difficult to determine from your code what the intent of the Images class is.

Is the use of header-less method implementations good practise or frowned upon?

If you write method implementations in Objective-C, it is pretty standard to sum up the methods of a class in the corresponding #interface blocks. Publically accessible methods go in the header file's interface, not-so-public methods can go in an empty category on top of the implementation file.
But it's not neccessary to declare an interface for every method. If you only reference the methods below their implementation code of the same class/file, there's no need to put any declaration anywhere else.
-(void) doSomething {
}
-(void) doSomethingElse {
[self doSomething];
}
Coming from another language, this is new to me. And I can't seem to decide whether it is nice and pretty to keep the interface blocks clean, or whether it should be prevented because the order of method implementations seem like a weird dependency to have.
What is the general public's opinion of this matter?
The general rule I follow is that if the only method calling doSomething is doSomethingElse then it's fine to not have doSomething be part of the declared private interface. But the moment a second method makes use of doSomething I add it to the declared interface.
The thinking behind this is that as long as the method is only ever called from one place there's no reason to think of it as modular or reusable code. Instead it's more like the method exists just to tidy up the implementation of its calling method. In essence, the method doesn't really stand on its own, so there's no point in treating it like an interface method. But as soon as a second method is making the same call it demonstrates that the code is in fact reusable and useful in more than just the original context, and able to stand on its own as a useful function. So at that point, it becomes a declared part of the private interface.
Some other coding style choices make answering this question really easy:
If you document every method at its declaration point, then not having a declaration means that either these methods are missing documentation, or they are documented at definition; either way it's inconsistent. If you follow the school of thought that most methods should be so self-explanatory from their name that they don't need documentation, this might not be an issue.
Some people advocate ordering methods from more general to more specific; in that model your example is ordered wrong, and the only way to fix it is to have a declaration.
There's also the question of whether you would find it annoying to get unexpected compiler errors when you do simple re-ordering or re-factoring just because you happened to start using a method earlier, and have to stop and add the declaration at that point.