Is it good style to declare methods in .h when they're intended to be overwritten by subclass? - iphone

I have a class which is intended to be abstract. This means: When someone subclasses it, a few methods MUST be overwritten.
But on the other hand, those methods are not intended to be called manually from anywhere except inside the abstract class (the superclass of the subclass).
Must I declare these methods in .h anyways or can I just add comments in .h which say "you must overwrite -foo and -bar"? Or is there a better pattern to make abstract methods?

Related: Is there a way to create an abstract class in Objective C?
Objective-C doesn't actually have a way to declare a class as abstract. From Apple's Docs:
Abstract Classes
Some classes are designed only or
primarily so that other classes can
inherit from them. These abstract
classes group methods and instance
variables that can be used by a number
of different subclasses into a common
definition. The abstract class is
typically incomplete by itself, but
contains useful code that reduces the
implementation burden of its
subclasses. (Because abstract classes
must have subclasses to be useful,
they’re sometimes also called abstract
superclasses.)
Unlike some other languages,
Objective-C does not have syntax to
mark classes as abstract, nor does it
prevent you from creating an instance
of an abstract class.
The NSObject class is the canonical
example of an abstract class in Cocoa.
You never use instances of the
NSObject class in an application—it
wouldn’t be good for anything; it
would be a generic object with the
ability to do nothing in particular.
The NSView class, on the other hand,
provides an example of an abstract
class instances of which you might
occasionally use directly.
Abstract classes often contain code
that helps define the structure of an
application. When you create
subclasses of these classes, instances
of your new classes fit effortlessly
into the application structure and
work automatically with other objects.
So to answer your question, yes, you need to place the method signature in the header, and should implement the method in the base class such that it generates an error if called, like the related question's answer states.
You can also use a protocol to force classes to implement certain methods.
However you choose to implement the base class, clearly document in the header, as well as in your documentation, exactly what the class assumes and how to go about sub-classing it correctly.

Whenever possible write your code so that improper implementations fail to compile. If you cannot do that then you should try to generate a runtime error (at the very least in a debug build) if the subclass is not written correctly. Do not rely on comments because people will not read them.

You must declare your "protected" and "abstract" methods in a header file, but you can use separate categories to clearly indicate their purpose and intended use.
#interface MyBaseClass : NSObject {
}
- (void)foo;
#end
#interface MyBaseClass(ProtectedMethods)
- (void)bar;
#end
#interface MyBaseClass(AbstractMethods) // Subclasses must implement
- (void)internalBar;
#end
You can put everything in a single header, or you could put your protected and abstract declarations in a separate "protected" header, say MyClassProtected.h, meant to be included only by your subclass implementations. It depends on how badly you want "hide" your protected methods.
Your base class can log, assert, or throw when an abstract/pure-virtual method is called.

As other people have said, Objective-C does not support pure virtual classes.
You can enforce pure virtual behaviour at runtime though. The cleanest way to do this is by using the Objective-C runtime's _cmd and NSObject's -doesNotRecognizeSelector:
- (void)iMustBeImplementedInaSubclass;
{
[self doesNotRecognizeSelector:_cmd]; // Pure virtual
}
As ben says you are probably better served by using a protocol to get your API design right.

Related

In Racket's class system, what do augment, overment, augride, etc. do?

Racket's documentation only partially describe what augment and pubment do: augment makes a method that executes after the superclass's version of that method, while pubment makes a method that will implicitly have the augment property if it is defined in a child class.
The docs say absolutely nothing about overment and augride, and I can't guess what they would do based on their names. What are they, and what is the difference between them?
The relatively large family of inheritance functions for Racket's class system is, as you describe, a little confusing, and their somewhat cutesy names don't always help.
In order to understand this, Racket provides two separate mechanisms for method inheritance.
public methods correspond to the classical idea of public methods in other OO models. Methods declared with public may be overridden in subclasses, unless they're declared final, in which case they cannot.
pubment methods are similar, but they cannot be overridden, only augmented. Augmenting a method is similar to overriding it, but the dispatch calls the superclass's implementation instead of the subclass's.
To clarify the difference between overriding and augmentation, when an overridden method is called, the overriding implementation is executed, which may optionally call the superclass's implementation via inherit/super. In contrast, in an augmented method, the superclass's implementation receives control, and it may optionally call the subclass's implementation via inner.
Now, we're also provided public-final, override-final, and augment-final. These are pretty simple. Declaring a method with public-final means it can neither be augmented nor overridden. Using override-final overrides a superclass's public method, but it doesn't allow any further overriding. Finally, augment-final is similar, but for methods declared with pubment, not public.
So then, what about the two weird hybrids, overment and augride?
overment can be used to implement methods initially defined with public. This "converts" them to augmentable methods instead of overridable methods for all the class's subclasses.
augride goes in the opposite direction. It converts an augmentable method to one that is overridable, but the overriding implementations only replace the augmentation, not the original implementation.
To summarize:
public, pubment, and public-final all declare methods that do not exist in a superclass.
Then we have a family of forms for extending superclass methods:
override and augment extend methods declared with public and pubment, respectively, using the relevant behaviors.
override-final and augment-final do the same as their non-final counterparts, but prevent further overriding or augmentation.
overment and augride convert overridable methods to augmentable ones and vice-versa.
For another, fuller explanation, you might be interested in taking a look at the paper from which Racket's model was derived, which is quite readable and includes some helpful diagrams.

On iOS, why can UIGestureRecognizer be instantiated, if it is an abstract class?

The following code using UIGestureRecognizer:
UIGestureRecognizer *gestureRecog = [[UIGestureRecognizer alloc]
initWithTarget:self
action:#selector(handletap:)];
[self.view addGestureRecognizer:gestureRecog];
can actually compile and run. I thought abstract class cannot be instantiated?
Abstract classes are not a language feature in Objective-C (unlike Java, for example), so it isn't something the compiler could enforce.
When a class is marked as abstract in the documentation, it is just a hint how it is intended to be used, but neither the runtime, nor the compiler will actually prevent you from instantiating it directly.
The section on abstract classes in the Objective-C Programming Language Guide actually states that NSView is an example of an abstract class that you may sometimes use without subclassing, so the concept as such is not as strict as in other languages/frameworks.
Thanks for omz's answer. This is the related excerpt from Apple's documentation:
Abstract Classes
Some classes are designed only or primarily so that other classes can
inherit from them. These abstract classes group methods and instance
variables that can be used by a number of subclasses into a common
definition. The abstract class is typically incomplete by itself, but
contains useful code that reduces the implementation burden of its
subclasses. (Because abstract classes must have subclasses to be
useful, they’re sometimes also called abstract superclasses.)
Unlike some other languages, Objective-C does not have syntax to mark
classes as abstract, nor does it prevent you from creating an instance
of an abstract class.
The NSObject class is the canonical example of an abstract class in
Cocoa. You never use instances of the NSObject class in an
application—it wouldn’t be good for anything; it would be a generic
object with the ability to do nothing in particular.
The NSView class, on the other hand, provides an example of an
abstract class, instances of which you might occasionally use
directly.
Abstract classes often contain code that helps define the structure of
an application. When you create subclasses of these classes, instances
of your new classes fit effortlessly into the application structure
and work automatically with other objects.

Objective-C Private Method Dilemma

I'm aware that Objective-C doesn't support real private methods. What I'm currently doing to declare 'private' methods is adding the following to class .m files:
#interface MyClass()
- (void) privateMethodName;
#end
The Problem:
If I now add a subclass, and want to use this 'private' method, I can't! I get the error:
Receiver type 'SubClassName' for instance message does not declare a
method with selector 'privateMethodName'
So, if I don't want non-subclasses to be able to access this method, but do want subclasses to be able to, what can I do? What is the best/proper way of achieving my goal?
You could separate the "protected" interface from the public one. In the primary header, just declare the public methods:
MyMagicThingy.h:
#interface MyMagicThingy: NSObject
- (void) publicMethod;
#end
Then, have an additional header with protected methods:
MyMagicThingy+Protected.h:
#import "MyMagicThingy.h"
#interface MyMagicThingy (Protected)
- (void) protectedMethods;
#end
You cannot have "real" private/protected/public methods in Objective C (as in: the compiler will enforce access rules. All methods are public). You have to go with a convention.
What you describe is really a protected method. One approach to overcome this: Ivars can be declared #public, #protected, or #private. You could declare a protected helper instance to restrict access to derived instances, which then calls back through the object which holds it.
Another alternative in some cases would be to make the subclasses write to an interface, then keep your implementation private.
Sometimes, you just have to document "don't do this, unless you are not a subclass" because it's not part of the language. In this mindset, a separate header which declares a category of protected methods is one of my favorite. It's pretty well hidden from clients, but can be made visible to subclasses by explicit inclusion -- Dirk provided an example of this at the same time, check it out.
Lastly, if you're comfortable with ObjC++, C++ offers this control, so you can mix modes and visibility quite freely.
First and foremost
You can't get anyone to not being able to call any method that is implemented on an object in Objective-C (at least not without burning through several dozen razors making Yaks less weatherproof).
Just don't call methods that are not declared in public header files, as a convention (this is, what you're already doing).
Second
The word public in the above paragraph does the trick:
In Objective-C (at least in its current incarnation), a class's interface can be defined over any number of header files using the technique you just described in your post: Class continuations.
One such example of an Apple framework class doing that would be UIGestureRecognizer with its separate subclassing header UIGestureRecognizerSubclass.h.
PS:
The error you are seeing reeks of using ARC so your runtime is definitely recent enough to even use multiple implementation files for that.

Is there a good/best way to extend a nested class in Objective-C?

Sometimes framework objects put helper class interfaces inside of *.m files, such as:
Foo.m:
#interface HelperObject : NSObject
/*...*/
#end
#implementation HelperObject
/*...*/
#end
#implementation Foo
/*...*/
#end
If I want to extend Foo, for instance using a category, is there a way to extend HelperObject as well? More generally, is doing so a violation of encapsulation? Should I try to extend the class functionality without extending HelperObject?
Callers of Foo know nothing about HelperObject--frequently, they do not even know it exists. So no, it's not safe or valid to be subclassing it in another file.
You can extend either Helper or Foo using categories, but you can't extend both with a single category. Given the relationship between Helper and Foo (where Helper is effectively an invisible helper class), I don't see much value in allowing that.
In general, Objective-C does not support multiple inheritance of either classes or categories.
It does, however, support multiple inheritance of interfaces through protocols.
That is, you could declare a protocol in your .m file that both Helper and Foo implement.
Objective C doesn't allow nested classes (unlike Java or C++ for example).
You can use aggregation to expand classes functionality. If you want to hide something you can use Pimpl idiom, however it is not necessary in ObjC cause you can easily replace that with category.
Edit: if you want to extend HelperObject object using category you should declare it in the same file where you want to use that functions (so they are visible).

Adding methods to an Objective C class interface is optional?

Coming from a C++ background, one thing that confuses me about Objective C is the fact that you can add a method to a class without actually specifying it in the class interface. So I had a barrage of questions:
Why would someone choose to not add the method in the class interface?
Is it simply because of visibility?
Methods without a declaration in the interface are private?
Is declaring methods in a class interface just optional?
Is it different for overriding a base class' method?
The main difference is that C++ sets up much of its inheritance and types at compile time and Objective C does it mostly at runtime.
The only differences in putting a method in the interface (if all parameters are objects) in objective-C are that the compiler can see it at compile time and check that an object could respond to the method - if it does not then you get a warning but the compilation does succeed and the program will run and loo for the method at runtime. If the method is in the implementation of the class or a category (or some other way) then the run time will find it and call it successfully.
There are NO private methods you can call any method.
I believe that this is the only way to create private methods in Objective-C. The language does not support the ability to declare a private method so by not declaring a method in the header file you are making private from all callers.
Proper data encapsulation requires that you lock down access to members that either expose data or manipulates it. Not all members ought to be exposed.
Yes it is.
Yes, this is true.
Yes, this is true as well.
This I am not sure about - perhaps someone with more Objective-C knowledge could answer this one.
Extending Andrew Hare's answer to answer 5, no, it doesn't: whether declared in an #interface or otherwise, method replacement/refinement works the same.