76

What's the difference between the two UpdateSubject methods below? I felt using static methods is better if you just want to operate on the entities. In which situations should I go with non-static methods?

public class Subject
{
    public int Id {get; set;}
    public string Name { get; set; }

    public static bool UpdateSubject(Subject subject)
    {
        //Do something and return result
        return true;
    }
    public bool UpdateSubject()
    {
        //Do something on 'this' and return result
        return true;
    }
}

I know I will be getting many kicks from the community for this really annoying question but I could not stop myself asking it.

Does this become impractical when dealing with inheritance?

Update:
Its happening at our work place now. We are working on a 6 month asp.net web application with 5 developers. Our architect decided we use all static methods for all APIs. His reasoning being static methods are light weight and it benefits web applications by keeping server load down.

Alexander
  • 1,169
  • 2
  • 10
  • 16

11 Answers11

95

I'll go with the most obvious problems of static methods with explicit "this" parameters:

  1. You lose virtual dispatch and subsequently polymorphism. You can never override that method in a derived class. Of course you can declare a new (static) method in a derived class, but any code that accesses it has to be aware of the entire class hierarchy and do explicit checking and casting, which is precisely what OO is supposed to avoid.

  2. Sort of an extension of #1, you can't replace instances of the class with an interface, because interfaces (in most languages) can't declare static methods.

  3. The unnecessary verbosity. Which is more readable: Subject.Update(subject) or just subject.Update()?

  4. Argument checking. Again depends on the language, but many will compile an implicit check to ensure that the this argument is not null in order to prevent a null reference bug from creating unsafe runtime conditions (kind of a buffer overrun). Not using instance methods, you'd have to add this check explicitly at the beginning of every method.

  5. It's confusing. When a normal, reasonable programmer sees a static method, they are naturally going to assume that it doesn't require a valid instance (unless it takes multiple instances, like a compare or equality method, or is expected to be able to operate on null references). Seeing static methods used this way is going to make us do a double or perhaps triple take, and after the 4th or 5th time we are going to be stressed and angry and god help you if we know your home address.

  6. It's a form of duplication. What actually happens when you invoke an instance method is that the compiler or runtime looks up the method in the type's method table and invokes it using this as an argument. You are basically re-implementing what the compiler already does. You're violating DRY, repeating the same parameter again and again in different methods when it's not needed.

It's hard to conceive of any good reason to replace instance methods with static methods. Please don't.

lennon310
  • 3,242
Aaronaught
  • 44,523
14

You've pretty much described exactly how you do OOP in C, in which only static methods are available, and "this" is a struct pointer. And yes, you can do run time polymorphism in C by specifying a function pointer during construction to be stored as one element of the struct. Instance methods available in other languages are just syntactic sugar that essentially does exactly the same thing under the hood. Some languages, like python, are halfway between, where the "self" parameter is explicitly listed, but special syntax for calling it handles inheritance and polymorphism for you.

Karl Bielefeldt
  • 148,830
12

The problem with static method comes the moment you need a sub-class.

Static methods cannot be overridden in sub-classes, hence your new classes cannot provide new implementations of the methods, making them less useful.

9

If you declare a method static, you do not have to instantiate an object from the class (using the new keyword) to execute the method. However, you can't refer to any member variables unless they are also static, in which case those member variables belong to the class, not a specific instantiated object of the class.

Put another way, the static keyword causes a declaration to be part of the class definition, so it becomes a single reference point across all instances of the class (objects instantiated from the class).

It follows, then, that if you want multiple running copies of your class, and you don't want the state (member variables) to be shared among all of your running copies (i.e. each object holds its own unique state), then you cannot declare those member variables static.

In general, you should use static classes and methods only when you are creating utility methods that accept one or more parameters, and return an object of some sort, without any side effects (i.e. changes to state variables in the class)

Robert Harvey
  • 200,592
5

The reason people argue that 'static methods show bad design' isn't necessarily due to the methods, it's actually static data, implicit or explicit. By implicit I mean ANY state in the program that isn't contained in the return value(s) or parameters. Modifying state in a static function is a throwback to procedural programming. However if the function does not modify state, or delegates state modification to component object functions, it's actually more a functional paradigm than procedural.

If you're not changing state, static methods and classes can have many benefits. It makes it much easier to ensure a method is pure, and thus free of side effects and any errors are fully reproducible. It also ensures that different methods in multiple applications using a shared library can be assured they will get the same results given the same input, making both error tracking and unit testing much easier.

Ultimately there's no difference in practice between oversized objects commonly seen such as 'StateManager' and static or global data. The benefit of static methods used correctly is they can indicate the author's intent to not modify state to later revisers.

4

This is a very interesting question that tends to have very different answers depending on the community you are asking it. Other answers seems to be C# or java bias : a programming language that is (mostly) pure object oriented and have a kind of idiomatic view of what object orientation is.

In other communities, such as C++, object orientation is interpret with more liberality. Some well knows experts have study the subject and, actually, conclude that free functions improve encapsulation (emphasis is mine):

We've now seen that a reasonable way to gauge the amount of encapsulation in a class is to count the number of functions that might be broken if the class's implementation changes. That being the case, it becomes clear that a class with n member functions is more encapsulated than a class with n+1 member functions. And that observation is what justifies my argument for preferring non-member non-friend functions to member functions

Scott Meyers

For those unfamiliar with C++ terminology:

  • member function = method
  • non-member function = static method
  • non-friend = use only public API
  • non-member non-friend function = static method that use only public API

Now, to answer you question :

Can't I just use all static methods?

No, you should not always use static methods.

But, you should use them whenever you only need to use the public API of a class.

authchir
  • 370
2

There's a lot of great answers here, and they're a lot more insightful and knowledgeabe than anything I could ever come up with as an answer, but I feel there's a little something that's not being adressed:

"Our architect decided we use all static methods for all APIs. His reasoning being static methods are light weight and it benefits web applications by keeping server load down."

(bold emphasis is mine)

My 2c on this part of the question is this:

Theoretically, what is said there is true: calling a static method only has the overhead of actually invoking that method. Calling a non-static (instance) method has the extra overhead of first instantiating the object, and at some point, destroying the instance (either manually or via some form of automatic garbage collection, depending on the platform used).

The play a little of devil's advocate on this: we can go even further and say stuff such as:

  • this can become really bad if an instance is created for each invocation of the (instance) method (as opposed to just leaving it static and calling it like that)

  • depending of the complexity of the constructor, the type hyerarchy, other instance members and other such unknown factors, the extra overhead of the non-static method call can vary and become really big

In truth, IMHO, the above points (and the general approach of "let's use statics because they're faster") are straw man arguments/assesments:

  • if the code is good, and, more specific to this argument, if the instances are created only when necessary (and destroyed in a an optimal fashion), then you do not get any extra overhead from using insance methods when appropriate (because if you only create the needed objects, those would have been created even if that method was declared as static some where else = same instanciation overhead)

  • by abusing static methods declaration in this way, it's possible to hide some issues with your code in regard to how instances are created (since the method is static an incorrect instanciation code may pass unnoticed until later, and that's never good).

2

Depending on the language and what you are trying to do, the answer may be that there's not a lot of difference, but the static version has a bit more clutter.

As your example syntax suggests Java or C#, I think Thorbjørn Ravn Andersen is right to point out the overriding (with late binding) issue. With a static method, there is no "special" parameter for late binding to be based on, so you can't have late binding.

In effect, a static method is just a function in a module, that module having the same name as the class - it isn't really an OOP method at all.

2

You're basically defeating the whole point of objects when you do this. There's a good reason we have pretty much shifted from procedural code to object oriented code.

I would NEVER declare a static method that took the class type as a parameter. That just makes the code more complex for no gain.

0

One additional point to add to the above answers is about code auto completion (i.e. Intellisense).

Say you have an object and you can’t remember what you can do with that object. In most OO languages, and most editors, you can type myObject.. After typing the period, you can see a list of every possible instance method available. This helps when examining code for the first time or after a long break and you don’t remember what you named a method.

With static functions you don’t get the same ease or reminders. Sure you could do MyType. And it would list the methods, but it’s not nearly as intuitive, and then you still have to reason about what parameters are needed, since there likely won’t be any no-parameter static methods.

Also you’d have to spend some mental effort to see and type out what Type it is. If the object is a return from a function or something, the Type might not be immediately obvious. Although this takes mere seconds to figure out, if you’re a developer those extra seconds add up real quick.

For this reason alone I try to avoid static methods if an instance alternative exists.

Adam B
  • 1,660
-3

in Java ...

Static methods are not overwritten but are hidden instead and so it would be a big difference (problem ?) in the case of extending the class.

On the other hand I noticed that Java programers have a tendency to think all HAS TO be object,without really to understand why, and I disagree.

Static should be used for code specific to the class. Static does not work well with inheritance.

some good examples of use of static methods are independent functions with no side effects.

also see the keyword synchronized...