1

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?

  • Are you distinguishing properly between 'declare' and 'define'? You must declare them in the base class for the sub-classes to be able to override them; you may decide not to define them in the header. – Jonathan Leffler Nov 02 '09 at 19:59
  • True but you still want somewhere to document what subclasses should do. I usually just have a section in the header with a comment labeled something like "for subclassing", although that is not a perfect solution since as the question asks, anyone can still call it... – Kendall Helmstetter Gelner Nov 02 '09 at 20:47
  • "overridden", not "overwritten". When you override a method in a subclass, the superclasses implementation of it still exists. – NSResponder Nov 04 '09 at 12:33

4 Answers4

5

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.

Community
  • 1
  • 1
Ben S
  • 68,394
  • 30
  • 171
  • 212
3

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.

Tim Post
  • 33,371
  • 15
  • 110
  • 174
Dolphin
  • 4,655
  • 1
  • 30
  • 25
2

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.

Darren
  • 25,520
  • 5
  • 61
  • 71
1

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.

Rog
  • 17,070
  • 9
  • 50
  • 73