I am trying to implement the concept of component programming while writing my iOS game.
In the book "Component Software: Beyond Object-Oriented Programming" by Clemens Szyperski, he mentions a tactic:
(not quote)
Start with a Duck class, which adds component Quack.
Class Quack implements an interface on whichever object that calls it, the interface specifies a method which uses Quacks quack()
With this setup, Duck has no reference or awareness about Quack except for when it's instantiated, and is never used in Duck thereafter. Other objects can call duckObject.quack() and reach Quack while only being aware of Duck object.
So far, I've been trying to implement this without success. Preferably, Duck should need no more code than instantiation, the rest placed in Quack class. Can this be done in Objective-C (for iOS?), or am I better off leaving COP for other languages?
I don't think there's an exact comparison in ObjC, but it sounds like you want to look into message forwarding. If an object is sent a message to which it doesn't respond, right before an error is signaled, the runtime sends the object forwardInvocation:, with an NSInvocation argument that encapsulates the message and arguments.
In forwardInvocation:, an object can pass along the invocation to another object which does handle that message. This allows a Duck instance to respond to the message quack, even though quack is not implemented by Duck, by holding a reference to an instance of Quack, which does implement it:
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if( [myQuack respondsToSelector:[anInvocation selector]] ){
[anInvocation invokeWithTarget:someOtherObject];
}
else{
[super forwardInvocation:anInvocation];
}
}
Not really sure what your question is. It sounds like you want a weak reference to a class.
First the duck class
//Duck.h
#import "Quack.h"
#interface Duck : NSObject {
Quack *quacker;
}
#property (nonatomic, retain) Quack *quacker;
#end
//Duck.m
#implementation Duck
#synthesize quarker;
-(id) init {
self = [super init];
if(self) {
}
return self;
}
-(Quack *)quacker {
if(quacker == nil) {
[self setQuacker:[[[Quack alloc] init] autorelease]];
}
return quacker;
}
#end
Then implement the Quack class.
//Quack.h
#interface Quack : NSObject {
}
-(void)quack;
#end
//Quack.m
#implementation Quack
-(id) init {
self = [super init];
if(self) {
}
return self;
}
-(void)quack {
NSLog(#"quack");
}
#end
Now in what ever class you want:
//RandomClass.m
[[[self duck] quacker] quack];
Related
How do I prevent a particular class from being subclassed?
I am not aware of such functionality (say final keyword for example) in the language. However Apple says it has done so for all classes in AddressBookUI.framework (in iOS)
For educational purposes, how can I achieve the same functionality, or how would they have done such thing?
From iOS7 Release Notes(Requires login) :
Here's one way: override allocWithZone: from within your "final" class (substituting MyFinalClassName for your actual class name) like this:
+ (id)allocWithZone:(struct _NSZone *)zone
{
if (self != [MyFinalClassName class]) {
NSAssert(nil, #"Subclassing MyFinalClassName not allowed.");
return nil;
}
return [super allocWithZone:zone];
}
This will prevent a subclass that is not a member of MyFinalClassName from being alloc'ed (and therefore init'ed as well), since NSObject's allocWithZone: must be called eventually, and by refusing to call super from your "final" class, you will prevent this.
There's a simpler way to prevent subclassing in Xcode 6 as a result of Swift interop. To prevent Swift classes from being subclassed in Objective-C the objc_subclassing_restricted is added to all class definitions in the {ProjectName}-Swift.h file.
You can use this in your projects:
#if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted)
# define FOO_FINAL __attribute__((objc_subclassing_restricted))
#else
# define FOO_FINAL
#endif
FOO_FINAL
#interface Foo : NSObject
#end
#interface Bar : Foo
#end
The compiler will halt on the definition of Bar with Cannot subclass a class with objc_subclassing_restricted attribute
Here is possible solution:
#interface FinalClass : NSObject
#end
#implementation FinalClass
- (id)init
{
if (self.class != [FinalClass class]) {
return nil;
}
self = [super init];
if (self) {
// instance initialization
}
return self;
}
#end
#interface InvalidSubclass : FinalClass
#end
#implementation InvalidSubclass
- (id)init
{
self = [super init];
if (self) {
}
return self;
}
#end
I'm not sure this is 100% guaranteed because it's runtime-checking anyway, but it should be enough to block and warn people that they should not subclass this. Subclass might skip superclass's init, but then the instance will not be usable because it's not fully initialised by superclass.
Something like the following will ensure that every time an "impossible subclass" calls +alloc, an object will be allocated that is an instance of FinalClass, and not the subclass. This is essentially what NSObject's +alloc method does, but here we specify an explicit class to create. This is how NSObject allocates instances (in Obj-C 2), but there is no guarantee this will always be the case, so you may want to add an appropriate -dealloc which calls object_dispose. This method also means you don't get a nil object back if you try to instantiate a subclass - you do get an instance of FinalClass.
#interface FinalClass: NSObject
//...
+ (id)alloc; // Optional
#end
// ...
#import <objc/runtime.h>
#implementation FinalClass
+ (id)alloc {
if (![self isMemberOfClass:[FinalClass class]]) {
// Emit warning about invalid subclass being ignored.
}
self = class_createInstance([FinalClass class], 0);
if (self == nil) {
// Error handling
}
return self;
}
#end
#interface InvalidSubclass : FinalClass
// Anything not in FinalClass will not work as +alloc will
// create a FinalClass instance.
#end
Note: I'm not sure I'd use this myself - specifying that a class shouldn't be subclassed is more in the nature of a design-contract with the programmer rather than an enforced rule at compile- or runtime.
I have a superclass and subclasses in the following format:
ParentClass.h
#interface ParentClass : NSObject
-(ParentClass *)field:(NSArray *)fields;
#end
ParentClass.m
#import "ParentClass.h"
#implementation ParentClass
-(id)init{
self = [super init];
if (self == nil) {
return self;
}
return self;
}
-(ParentClass *)field:(NSArray *)fields{
ParentClass *pc = [[ParentClass alloc] init];
// code
return pc;
}
#end
Subclass.h
#interface Subclass : ParentClass
-(Subclass *)field:(NSArray *)fields;
#end
Subclass.m
#import "Subclass.h"
#implementation Subclass
-(id)init{
self = [super init];
if (self == nil) {
return self;
}
return self;
}
-(Subclass *)field:(NSArray *)fields{
// code
return (Subclass *)[self field:fields];
}
#end
I guess the issue is here.
return (Subclass *)[self field:fields];
I'm not accessing the parent class method the way I should. Can anyone tell what should be the right way instead?
What if i call this way?
-(Subclass *)subClassField:(NSArray *)fields{
return (Subclass *)[self field:fields];
}
and i replaced the
-(Subclass *)field:(NSArray *)fields;
with
-(Subclass *)subClassField:(NSArray *)fields;
First please note that this code
-(ParentClass *)field:(NSArray *)fields{
ParentClass *pc = [[ParentClass alloc] init];
// code
return pc;
}
Doesn't look right from the software design perspective. From what you posted it seems that ParentClass instances can create and return other instances of its own type from the field method. This doesn't look ok, but it could be fine depending on what your intentions are.
Consider making ParentClass and FieldClass different classes if that makes sense.
Regarding the subclass, the way of doing what you want would be this:
-(ParentClass *)field:(NSArray *)fields
{
// code
return [super field:fields];
}
Note that I changed the returned type to be (ParentClass *), and the self to super. You cannot return a ParentClass object in the place of a SubClass object (the latter could have extra data that former doesn't know about). Doing the opposite is valid (you can return a Subclass object when someone expects to receive an object of ParentClass type).
Having said that is pretty unclear what you're trying to achieve, I'll tell what's wrong. First of all isn't enough to cast a pointer to a base class pointer, to call the superclass method, you should call it this way:
return (Subclass*) [super field:fields]; // Still wrong
But you're break polymorphism, and as the method signature says, you're returning a Subclass object, and the user that calls this method expects to have a Subclass object, but at the first call of a method that is just implemented by the subclass, it crashes because you're returning an instance of the superclass. Maybe is enough for you to change the method signature to return a ParentClass pointer, but this makes the method useless, why overriding it? It isn't pretty clear what you're trying to do, and what's your logic path.
Edit
Having seen the code that you posted on Github, here the situation is pretty different. In the Java code,t he method field returns this, so no new object gets created, and the method is just used for side effects. The add method doesn't break polymorphism, because just the object reference is of the parent class type, but if executed on a subclass it returns the object itself (this), which is of the subclass type.
In Objective-C for these cases the id type is used, which is used to represent a whatever object pointer, to a whatever class. You could also use the ParentClass type, but I'll stick to conventions. Here's an indicative code:
#implementation ParentClass
#synthesize endpoint
- (id) add: (NSString*) endpoint fields: (NSArray*) fields
{
<code>
return self;
}
- (id) field: (NSArray*) fields
{
return [self add: self.endpoint fields: fields];
}
#end
#implementation SubClass
- (id) field: (NSArray*) fields
{
< Additional code >
return [self add: self.endpoint fields: fields];
}
#end
I read a topic at here
http://www.mikeash.com/pyblog/friday-qa-2010-05-14-what-every-apple-programmer-should-know.html. Mike said that "Always use [self class] when invoking your own class methods". But I don't understand why. Can you give an example ?
Lets say that you have class foo, which have the following methods:
+(NSString*) bar{ return #"bar"; }
-(NSString*) barMethod{ return [[self class] bar]; }
Now lets say that you have a class foo2 which inherits from foo. If you override
+(NSString*) bar { return #"bar2" }
the method barMethod will return bar2, as you probably intended for it to.
Unlike other OO languages, class methods in Objective-C are both inherited and can be overridden.
Thus, if you have:
#immplementation Abstract // : NSObject
- (void) doSomethingClassy
{
[Abstract classyThing];
}
+ (void) classyThing
{
... some classy code ...;
}
#end
#interface Concrete : Abstract
#end
#implementation Concrete
+ (void) classyThing
{
... some classy code ...;
[super classThing];
}
#end
Then this won't call Concrete's +classyThing from Abstract's implementation of doSomethingClassy:
[[[Concrete alloc] init] doSomethingClassy];
Whereas if you modify doSomethingClassy to do [[self class] classyThing]; it'll work as expected.
(note that this is a concrete example of Liye Zhang's answer -- feel free to mark his correct as he was first, just not with quite as concrete of an example)
Here is template method pattern , Java and C++ can implement it easily with virtual function. How about Object C to implement this pattern ? Any example in cocoa touch (iOS) ?
As jer has already pointed out, all Objective-C methods are essentially virtual. It is a feature of the language which does not quite mesh with other C-like languages. That being said, the basics of the template method pattern can still be achieved in Objective-C, by "manually" forcing subclasses to implement certain functions. For example (using the convention in your linked Wikipedia article):
#interface Game
{
int playersCount;
}
- (void)playOneGame:(int)numPlayers;
// "virtual" methods:
- (void)initializeGame;
- (void)makePlay:(int)player;
- (BOOL)endOfGame;
- (void)printWinner;
#end
#implementation Game
- (void)initializeGame { NSAssert(FALSE); }
- (void)makePlay:(int player) { NSAssert(FALSE); }
- (BOOL)endOfGame { NSAssert(FALSE); return 0; }
- (void)printWinner { NSAssert(FALSE); }
- (void)playOneGame:(int)numPlayers
{
//..
}
#end
The above code forces subclasses of Game to override the "virtual" methods by throwing an exception the moment one of the base class implementations is called. In effect, this moves the test from the compiler stage (as it would be in C++ or Java) and into the runtime stage (where similar things are often done in Objective-C).
If you really want to enforce the rule that subclasses are not allowed to override the playOneGame: method, you can attempt(*) to verify the correct implementation from within the init method:
#implementation Game
...
- (void)init
{
if ((self = [super init]) == nil) { return nil; }
IMP my_imp = [Game instanceMethodForSelector:#selector(playOneGame:)];
IMP imp = [[self class] instanceMethodForSelector:#selector(playOneGame:)];
NSAssert(imp == my_imp);
return self;
}
...
#end
(*) Note that this code does not result in a 100% rock-solid defense against subclasses which re-implement playOneGame:, since the very nature of Objective-C would allow the subclass to override instanceMethodForSelector: in order to produce the correct result.
In Objective-C all methods are akin to C++ virtual methods.
In Objective-C Template Method Pattern is Used When you have a Skeleton of an Algorithm but it can be Implemented in different ways. Template method defines the steps to execute an algorithm and it can provide default implementation that might be common for all or some of the subclasses.
Let's take an example but First Look at the Picture
#interface Worker : NSObject
- (void) doDailyRoutine;
- (void) doWork; // Abstract
- (void) comeBackHome;
- (void) getsomeSleep;
#end
#implementation Worker
- (void) doDailyRoutine {
[self doWork];
[self comeBackHome];
[self getsomeSleep];
}
- (void) doWork { [self doesNotRecognizeSelector:_cmd]; }
- (void) comeBackHome { [self doesNotRecognizeSelector:_cmd]; }
- (void) getsomeSleep { [self doesNotRecognizeSelector:_cmd]; }
// [self doesNotRecognizeSelector:_cmd] it will force to call the subclass Implementation
#end
#interface Plumber : Worker
#end
#implementation Plumber
- (void) doWork { NSLog(#“Plumber Work"); }
#end
#interface Electrician : Worker
#end
#implementation Electrician
- (void) doWork { NSLog(#“Electrician Work"); }
#end
#interface Cleaner : Worker
#end
#implementation Cleaner
- (void) doWork { NSLog(#“Cleaner Work"); }
#end
In this example dowork() is an Abstract function which should be implemented by all the subclasses and this pattern is largely used in Cocoa Frameworks.
Hope it will help you to Understand the "Template Method Pattern".
I'm new to the Objective C business (Java developer most of the time) and am woking on my first killer app now. :-)
At the moment I am somehow confused about the usage of selectors as method arguments. They seem to be a little bit different than delegates in C# for example.
Given the following method signature
-(void)execute:(SEL)callback;
is there a way to enforce the signature for the selector passed to such a method?
The method is expecting a selector of a method with the following signature
-(void)foo:(NSData*)data;
But the SEL (type) is generic, so there is a good chance to pass a wrong selector to the
execute method. OK at least at runtime one would see a funny behavior... but I would like to see a compiler warning/error when this happens.
The quick answer is: no, there is no way to have the compiler enforce the method signature of a method selector that is provided via a SEL argument.
One of the strengths of Objective-C is that it is weakly-typed language, which allows for a lot more dynamic behaviour. Of course, this comes at the cost of compile-time type safety.
In order to do what (I think) you want, the best approach is to use delegates. Cocoa uses delegates to allow another class to implement "callback"-type methods. Here is how it might look:
FooController.h
#protocol FooControllerDelegate
#required:
- (void)handleData:(NSData *)data forFoo:(FooController *)foo;
#end
#interface FooController : NSObject
{
id <FooControllerDelegate> * delegate;
}
#property (assign) id <FooControllerDelegate> * delegate;
- (void)doStuff;
#end
FooController.m
#interface FooController (delegateCalls)
- (void)handleData:(NSData *)data;
#end
#implementation FooController
#synthesize delegate;
- (id)init
{
if ((self = [super init]) == nil) { return nil; }
delegate = nil;
...
return self;
}
- (void)doStuff
{
...
[self handleData:data];
}
- (void)handleData:(NSData *)data
{
if (delegate != nil)
{
[delegate handleData:data forFoo:self];
}
else
{
return;
// or throw an error
// or handle it yourself
}
}
#end
Using the #required keyword in your delegate protocol will prevent you from assigning a delegate to a FooController that does not implement the method exactly as described in the protocol. Attempting to provide a delegate that does not match the #required protocol method will result in a compiler error.
Here is how you would create a delegate class to work with the above code:
#interface MyFooHandler <FooControllerDelegate> : NSObject
{
}
- (void)handleData:(NSData *)data forFoo:(FooController *)foo;
#end
#implementation MyFooHandler
- (void)handleData:(NSData *)data forFoo:(FooController *)foo
{
// do something here
}
#end
And here is how you would use everything:
FooController * foo = [[FooController alloc] init];
MyFooHandler * fooHandler = [[MyFooHandler alloc] init];
...
[foo setDelegate:fooHandler]; // this would cause a compiler error if fooHandler
// did not implement the protocol properly
...
[foo doStuff]; // this will call the delegate method on fooHandler
...
[fooHandler release];
[foo release];
To directly answer your question, no, the SEL type allows any type of selector, not just ones with a specific signature.
You may want to consider passing an object instead of a SEL, and document that the passed object should respond to a particular message. For example:
- (void)execute:(id)object
{
// Do the execute stuff, then...
if ([object respondsToSelector:#selector(notifyOnExecute:)]) {
[object notifyOnExecute:self];
}
// You could handle the "else" case here, if desired
}
If you want to enforce the data handling, use isKindOfClass inside your selector. This works a lot like instanceof which you are familiar with in Java.