Fog Creek Software
g
Discussion Board




Class (static) methods and inheritance

I started thinking about this on and off due to a discussion a month ago here on "best practices" and declaring all your methods static and final if possible.

Why can't you override static (class) methods in subclasses?

I can think of a number of reasons, I'm not sure which one's the clincher:

1) If you look at java assembler, you'll see that the opcode that invokes virtual methods ("methods which might be overriden in subclasses") always expects an instance of an object, while the opcode that invokes static methods requires an object that represents a class.
So you can't call one with the other. But nothing would prevent the compiler from inserting a getClass() statement between the object and the static method call, so that argument doesn't seem right.

2) "If you'll call the method on an object and want polymorphism, you should never even NEED to declare your method as static".
It's hard coming up with a good simple example, but what about this: Amazon needs to represent different types of products (CD's, books, washing machines, ...), and each of these has a prefix to their serial numbers ("CD No","ISBN", "WM"). Each of these product sub-types would be subclasses of the 'product' class.
Sometimes we'll need to get the prefix from the class (e.g. user selects product type from dropdown, and we fill in the first few characters of the search screen for him). Sometimes we'll need to get the prefix from an object (e.g. fullSerialNumber = getPrefix() + getSerialNumber() ).
So I'm not so sure about this second argument either.

Your thoughts?

Yves
Wednesday, February 25, 2004

I think you should be able to on the give me enough rope to shoot my whole darn leg off and then hang me from a tree principle

But in C++ it's absence is a consequence of the implementation as well as any bigger OO principles that might apply.

S. Tanna
Wednesday, February 25, 2004

I think there's a more fundamental reason. A static method is intended to do things that are relevant to the class, not to objects of that class. If you could override what it did in a derived class, then you'd be changing how the base class behaved.

Let's take a concrete example. I have a base class: Product, and some derived classes: Book, CD, DVD that inherit from Product. Let's say that Product has a static method "TotalProducts()" that tells you the total number of products in existence. The important point is that TotalProducts() applies to _all things that are products_, whether they be Books, CDs, DVDs or whatever. That is, all classes that inherit from Product, are Products -- that's what inheritance means, it models an "is-a" relationship. Since a Book "is a" Product, and a DVD "is a" product, there can be no reason that they'd want to override "TotalProducts()" -- after all, if they had different behaviour, they wouldn't "be" a Product!

Of course, this is a contrived example (I recall Joel mentioning somewhere that with contrived examples you can prove anything!) I'm sure someone will come up with an example where it makes perfect sense to override a static method. But the general idea is that derived classes shouldn't change their base class behaviour.

Adrian Gilby
Wednesday, February 25, 2004

It's because types are not polymorphic -- only objects are. Overriding instance methods means you can invoke x.Foo() where x is a Bar reference, and actually execute Baz.Foo() where Baz was derived from Bar.

You can pick which one you want at the time when the object is created -- just select the proper type. Polymorphism is possible because object creation and object use are disconnected: use is polymorphic, creation is not.

That cannot work with statics because this distinction does not exist here. You always invoke them on the type name, so you have to write Bar.Foo() and now the compiler/runtime has no way of figuring out that you might want to call Baz.Foo() instead.

In other words, if you allowed overriding static methods the base class methods would be _completely_ inaccessible -- how would you ever call them if any Bar.Foo() call got rerouted to Baz.Foo()?

Hmm... actually, it might work in C++ where you can call statics on instances.

Chris Nahr
Wednesday, February 25, 2004

Chris - props for the good explanation.

Adrian - not to beat a dead horse, but you should think of "is-substitutable-for" rather than "is-a" when thinking about inheritance. See http://www.parashift.com/c++-faq-lite/proper-inheritance.html and look at [21.8].

Exception guy
Wednesday, February 25, 2004

Chris,

except the compiler could just have the rule if you call Baz.foo() it calls the method associated with Baz and if you call Bar.foo() it could call the method associated with Bar.

name withheld out of cowardice
Wednesday, February 25, 2004

I have a memory that this is covered in "Effective Java".

name withheld out of cowardice
Wednesday, February 25, 2004

You can do it in smalltalk. It's not that it's conceptually impossible in C++/C#/Java, but rather they decided not to for various implementation and philosophical reasons.

Sum Dum Gai
Wednesday, February 25, 2004

name,

It already does this. You can hide (the best you can hope for in C#) a static using the new keywork, and then when you call Baz.Foo() you get the Baz version, and Bar.Foo() you get the Bar version.

This isn't polymorphism, obviously.

Brad Wilson (dotnetguy.techieswithcats.com)
Wednesday, February 25, 2004

What Brad said. The whole point of polymorphism is that you write one type name in a piece of code, but at execution time the method/property/whatever of a _different_ (derived) type is accessed.

Chris Nahr
Thursday, February 26, 2004

Sum Dum Gai: how does static polymorphism work in Smalltalk? Do you access statics through instances then, as you can in C++?

Chris Nahr
Thursday, February 26, 2004

In Smalltalk, everything is an object. Including classes. So yes, you do access statics via an instance: the class object instance, as opposed to an instance of the class.

And yes, this does get confusing very quickly. :-)

Chris Tavares
Thursday, February 26, 2004

*  Recent Topics

*  Fog Creek Home