Introducing attribute objc_pure_virtual_method

Hi,

currently there is no possibility in objective-c to mark a method as “pure virtual” like in C++. I think the “pure-virtual”-construct enables an elegant and clean way to describe and specify APIs, although if it may be a rarely used construct.
A workaround for objective-c is to declare the method within the base-class and add to it’s implementation an assertion like assert(false && “has to be implemented by subclasses”). But i think it would be nicer when the compiler gives me a hint that there is something wrong, instead of crashing the app at runtime.

So, with my attached patch I’m introducing an attribute for that case, named objc_pure_virtual_method. It can only be attached to methods of a class-declaration (the other way round: extensions, categories and protocols are excluded). If a subclass does not implement the method, it will cause a warning. If the subclass redeclares the method within it’s @interface-declaration and also adds the objc_pure_virtual_method, no warning will be generated. If the call of an init-method to an instance of a class with pure virtual methods is detected, an error is generated.

I’m not sure if the init-call to a subclass of an abstract class, that did not implement all pure virtual methods, should also produce an error, as this case already produces warnings of unimplemented methods - in my eyes, this is sufficient.

Surely there are some issues with my current implementation, as i’m not so sure if i have chosen the right places to add the logic and about the names / warnings i have chosen and I’m happy to hear any suggestion / criticism.

clang_objc_pure_virtual_method.diff (14.4 KB)

Hi there,

I think this an interesting direction to explore. I have a few concerns about the model, as it doesn’t feel quite there yet.

(1) If a method is marked virtual in a class, should there be a warning to implement that method in the same class?

(2) In a subclass, if a method is redeclared as being “non-virtual”, should we also guarantee that it is implemented in the @implementation? That may be tricky of course with categories.

It also seems like we should exclude this attribute to being applied to certain method families, such as “init”, as there are other idioms at play there.

Minor nit:

“classdeclaration”

For clarity (and to fix the typo), just say “class’s @interface"

Once we resolve some of these questions, I’d also like to discuss this with a few others off list (particularly framework authors), as this is essentially a language change.

Cheers,
Ted

currently there is no possibility in objective-c to mark a method as "pure
virtual" like in C++. I think the "pure-virtual"-construct enables an
elegant and clean way to describe and specify APIs, although if it may be a
rarely used construct.
A workaround for objective-c is to declare the method within the
base-class and add to it's implementation an assertion like assert(false &&
"has to be implemented by subclasses"). But i think it would be nicer when
the compiler gives me a hint that there is something wrong, instead of
crashing the app at runtime.

So, with my attached patch I'm introducing an attribute for that case,
named objc_pure_virtual_method. It can only be attached to methods of a
class-declaration (the other way round: extensions, categories and
protocols are excluded). If a subclass does not implement the method, it
will cause a warning. If the subclass redeclares the method within it's
@interface-declaration and also adds the objc_pure_virtual_method, no
warning will be generated. If the call of an init-method to an instance of
a class with pure virtual methods is detected, an error is generated.

I'm not sure if the init-call to a subclass of an abstract class, that did
not implement all pure virtual methods, should also produce an error, as
this case already produces warnings of unimplemented methods - in my eyes,
this is sufficient.

Surely there are some issues with my current implementation, as i'm not so
sure if i have chosen the right places to add the logic and about the names
/ warnings i have chosen and I'm happy to hear any suggestion / criticism<dict.cc | englisch-deutsch/criticism.html> | English Dictionary;
.

I have also been in a situation where I have done the assert(false && "has
to be implemented by subclasses") thing, but it is very rare. In Objective
C subclassing is (compared to most OOP languages) infrequent and shallow.
Since most the framework code in Cocoa/CocoaTouch/GNUStep chooses to use
delegation as opposed subclassing it is generally possible to achieve the
same sort of compile time warnings by having @required methods in a formal
protocol on a delegate.

While I am generally in favor of adding annotations, I wonder if it is
worthwhile to add an annotation for something that is really not a common
idiomatic pattern in the language?

(2) In a subclass, if a method is redeclared as being “non-virtual”, should

we also guarantee that it is implemented in the @implementation? That may
be tricky of course with categories.

I suspect you can get into similar situations today where the compiler does
not have enough info to do things with @required in formal protocols and
categories. I am sure you can if you are using class_addMethod to provide
the IMPs at runtime. The language already provides @dynamic for dealing
with that with respect to properties. Extending @dynamic to methods would
work for the proposed annotation (if it makes sense to do the annotation at
all) and solve the issue with formal protocols (though in practice I am not
sure I have seen the cases ever come up, they are sort of pathological).

Louis

Thanks Louis. I was also thinking about this some more this evening and exchanged some thoughts with others, and I think I agree with you that this doesn’t seem worth adding to the language.

Also, it seems like this could easily be modeled using protocols. The subclass could implement a protocol with the required method, and use -Wprotocol to catch when something isn’t implemented.

varadictemplate: Do you see a compelling need for this that cannot be modeled using protocols? The class adopting the protocol is saying “all methods are implemented” for that protocol, which is natural way to express not only that a particular method is implemented, but that a group of methods are implemented.

My 2 cents (even if the feature does not end up in clang).
The concept of "pure virtual" may be clear for people common from C++, but I dont think this is the right wording to choose for Objective-C.
The Apple documentation never ever mentions the term virtual once for objective-c. I think the word commonly used is "abstract" so a better name for this attribute could be objc_abstract_method .

-- Jean-Daniel

Thank you for all your comments.

And even that is quite rare. A more common notion in Objective-C is a primitive method (e.g. -length and -characterAtIndex: in NSString), which is then used to implement all of the others and must be implemented in subclasses.

It would be interesting to have a language feature that can check these (and make them more obvious - I've seen numerous instances of people skim-reading documentation and not identifying all of the methods that they must implement). It would be cleaner, from a documentation standpoint, to be able to mark a protocol that a class implemented as requiring reimplementation in all subclasses. Then it could be something that was both obvious in the documentation and checkable in the compiler.

David

It would be cleaner, from a documentation standpoint, to be able to mark a protocol that a class implemented as requiring reimplementation in all subclasses. Then it could be something that was both obvious in the documentation and checkable in the compiler.

Right. This follows on my comment about protocols in my previous email:

varadictemplate: Do you see a compelling need for this that cannot be modeled using protocols? The class adopting the protocol is saying “all methods are implemented” for that protocol, which is natural way to express not only that a particular method is implemented, but that a group of methods are implemented.

I think my reasoning was a bit imprecise here. The base class likely wants to adopt the protocol as well, but force the protocol to be implemented by subclasses. This seems like a more general mechanism than just annotating individual methods.

variadictemplate: what do you think?

Thank you for all your comments.

Sorry, there was a missing word in my sentence (a typo). I meant that if they did implement the method in the base class, then they would get a warning. What I said was indeed contradictory.

That seems reasonable.

Another approach is in my reply to David Chisnall (later in this thread). Instead of this being about specific methods, perhaps we can make this about protocols instead.

(I’m sorry i currently can’t answer more recently)

2013/10/30 Ted Kremenek <kremenek@apple.com>