16

In answers to this question, the general consensus was that static methods are not meant to be overridden (and thus static functions in C# cannot be virtual or abstract). This is not only the case in C#, though; Java also forbids this and C++ doesn't seem to like it either. However, I can think of many examples of static functions that I'd want to override in a child class (for example, factory methods). While in theory, there are ways to get around them, none of them are clean or simple.

Why shouldn't static functions be overrideable?

5 Answers5

15

With the static methods, there is no object to provide proper control of the override mechanism.

The normal class/instance virtual method mechanism allows for finely tuned control of overrides as follows: each real object is an instance of exactly one class. That class determines the behavior of the overrides; it always gets the first crack at virtual methods. It can then choose to call parent method at the right time for it's implementation. Each parent method then also gets its turn to invoke its parent method. This results in a nice cascade of parent invocations, which accomplishes one of the notions of reuse of code that object orientation is known for. (Here the base/super classes' code are being reused in a relatively complex way; another orthogonal notion of code reuse in OOP is simply having multiple object of the same class.)

Base classes can get reused by various subclasses, and each can coexist comfortably. Each class that is used to instantiate objects dictating its own behavior, peacefully and simultaneously coexisting with the others. The client has control over which behaviors it wants and when by choosing which class to use to instantiate an object and pass around to others as desired.

(This is not a perfect mechanism, as one can always identify capabilities that are not supported, of course, which is why patterns like factory method and dependency injection are layered on top.)

So, if we were to make an override capability for statics without changing anything else, we would have difficulty ordering the overrides. It would be hard to define a limited context for the applicability of the override, so you would get the override globally rather than more locally like with objects. There is no instance object to switch the behavior. So, if someone invoked the static method that happened to have been overridden by another class, should the override get control or not? If there are multiple such overrides, who gets control first? second? With instance object overrides, these questions all have meaningful and well-reasoned answers, but with statics they do not.

Overrides for statics would be substantially chaotic, and, things like this have been done before.

For example, the Mac OS System 7 and prior used a trap patching mechanism for extending the system by getting control of application-made system calls before the operating system. You could think of the system call patch table as an array of function pointers, much like a vtable for instance objects, except that it was a single global table.

This caused untold grief for programmers because of the unordered nature of the trap patching. Whoever got to patch the trap last basically won, even if they didn't want to. Each patcher of the trap would capture the previous trap value for a sort-of parent call capability, which was extremely fragile. Removing a trap patch, say when you no longer needed to know about a system call was considered bad form as you didn't really have the information needed to remove your patch (if you did it you would also unpatch any other patches that had followed you).

This is not to say that it would be impossible to create a mechanism for overrides of statics, but what I would probably prefer to do instead is turn the static fields and static methods into instances fields and instance methods of metaclasses, so that the normal object orientation techniques would then apply. Note that there are systems that do this as well: CSE 341: Smalltalk classes and metaclasses; See also: What is the Smalltalk equivalent of Java's static?


I'm trying to say that you would have to do some serious language feature design to make it work even reasonably well. For one example, a naive approach was done, did limp along, but was very problematic, and arguably (i.e. I would argue) architecturally flawed by providing an incomplete and difficult to use abstraction.

By the time you're done designing the static overrides feature to work nicely you might have just invented some form of metaclasses, which is a natural extension of OOP into/for class-based methods. So, there is no reason not to do this -- and some languages actually do. Perhaps it is just a bit more of a fringe requirement that a number of languages choose not to do.

Erik Eidt
  • 34,819
10

Overriding depends on virtual dispatch: you use the runtime type of the this parameter to decide which method to call. A static method has no this parameter, so there's nothing to dispatch on.

Some languages, notably Delphi and Python, have an "in-between" scope that allows for this: class methods. A class method is not an ordinary instance method, but it's not static either; it receives a self parameter (amusingly, both languages call the this parameter self) that's a reference to the object type itself, rather than to an instance of that type. With that value, now you have a type available to do virtual dispatch on.

Unfortunately, neither the JVM nor the CLR has anything comparable.

Mason Wheeler
  • 83,213
3

You ask

Why shouldn't static functions be overrideable?

I ask

Why should functions you wish to override be static?

Certain languages force you to start the show in a static method. But after that you really can solve a great many problems without any more static methods at all.

Some people like to use static methods anytime there is no dependence on state in an object. Some people like to use static methods for construction of other objects. Some people like to avoid static methods as much as possible.

None of these people are wrong.

If you need it to be overridable just stop labeling it static. Nothings going to break because you have a stateless object flying around.

candied_orange
  • 119,268
3

Why shouldn't static methods be able to be overrideable?

It's not a question of "should".

"Overriding" means "dispatch dynamically". "Static method" means "dispatch statically". If something is static, it cannot be overridden. If something can be overridden, it isn't static.

Your question is rather akin to asking: "Why shouldn't tricycles be able to have four wheels?" The definition of "tricycle" is that has three wheels. If it's a tricycle, it can't have four wheels, if it has four wheels, it can't be a tricycle. Likewise, the definition of "static method" is that it is statically dispatched. If it's a static method, it can't be dynamically dispatched, if it can be dynamically dispatched, it can't be a static method.

It is, of course, perfectly possible to have class methods that can be overridden. Or, you could have a language like Ruby, where classes are objects just like any other object and thus can have instance methods, which completely eliminates the need for class methods altogether. (Ruby only has one kind of methods: instance methods. It has no class methods, static methods, constructors, functions, or procedures.)

Jörg W Mittag
  • 104,619
1

thus static functions in C# cannot be virtual or abstract

In C#, you always call static members using the class, eg BaseClass.StaticMethod(), not baseObject.StaticMethod(). So eventually, if you have ChildClass inheriting from BaseClass and childObject an instance of ChildClass, you will not be able to call your static method from childObject. You will always need to explicitly use the real class, so a static virtual just doesn't make sense.

What you can do is redefine the same static method in your child class, and use the new keyword.

class BaseClass {
    public static int StaticMethod() { return 1; }
}

class ChildClass {
    public static new int StaticMethod() { return BaseClass.StaticMethod() + 2; }
}

int result;    
var baseObj = new BaseClass();
var childObj = new ChildClass();

result = BaseClass.StaticMethod();
result = baseObj.StaticMethod(); // DOES NOT COMPILE

result = ChildClass.StaticMethod();
result = childObj.StaticMethod(); // DOES NOT COMPILE

If it were possible to call baseObject.StaticMethod(), then your question would make sense.