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.

14
  • 10
    Rich Hickey would encourage something non-idiomatic like that (all static methods). If you like a functional style, you might as well use a functional language ;) Not everything in software is best modeled as an object.
    – Job
    Aug 3, 2011 at 2:29
  • 15
    @Job: I don't really see how this is functional - it's procedural.
    – Aaronaught
    Aug 3, 2011 at 4:16
  • 2
    @Job: This class is not immutable.
    – Aaronaught
    Aug 4, 2011 at 2:58
  • 3
    @DonalFellows: Of course you can, C# and F# are both mixed-paradigm. But the fact remains, static methods != functional programming. FP means passing/chaining functions, immutable data types, avoidance of side-effects, etc. That's completely opposite of what the code snippet in the OP does.
    – Aaronaught
    Jan 22, 2012 at 19:44
  • 5
    "His reasoning being static methods are light weight and it benefits web applications by keeping server load down". That is wrong. Keeping the server load down?
    – mamcx
    Sep 1, 2013 at 1:17

11 Answers 11

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.

7
  • 5
    +1 for your final line alone. I wish a lot more people would think "instance method" before they think "static method". Jan 22, 2012 at 20:41
  • 4
    +1. I would add that static methods make it hard-to-impossible to write tests, as in most cases you can't mock them: once any portion of your code depends on a static method, you can't substitute it with a no-op in your tests. A prime example in the .NET world would be classes like File, FileInfo and DirectoryInfo (and in fact, there are libraries which hide them behind interfaces that can then be injected as needed and mocked out in tests).
    – s.m
    Jul 2, 2014 at 20:25
  • I think your points on polymorphism/inheritance are moot. one shouldn't use inheritance for code reuse, so that's irrelevant. the inheritance part is also dubious. in most modern languages, method signatures are polymorphic in themselves. if you take a functional approach you start passing around methods and you compose complex methods out of simple ones that are interchangeable based on their interface. there are basiaclly no drawbacks to static methods that aren't offset by simply designing with them in mind, same as with OOP.
    – sara
    Jun 28, 2016 at 15:19
  • 2
    @s.m that's simply not true. if you have a hard dependency on ANYTHING, static or not, that can't be in a unit test, then it's untestable, period. static doesn't cause this. a static method can be injected the same way a class representing a db connection can. you're assuming that "static" means "static plus hard hidden dependencies touching global state and external resources". that's not fair.
    – sara
    Jun 28, 2016 at 15:21
  • 1
    @s.m if your function is dependent ONLY on "something that transforms Foos into Bars" and not "I'm gonna secretly reference this class with a method in it without telling anyone" (which would be analogous to newing up dependencies which is also untestable), then ANY such transformer will do. if you work in an ancient language where functions/methods cannot be passed as arguments or returned by functions then sure, it'll require more boiler plate, but that's a pretty big restriction. you can even pass methods in java by now. the point still stands: static methods are not untestable
    – sara
    Jun 28, 2016 at 16:12
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.

3
  • FWIW, with C you can do virtual dispatch like this: obj->type->mthd(obj, ...); and that's substantially similar to what happens with virtual dispatch in other languages (but behind the scenes). Jan 22, 2012 at 15:44
  • @Karl Can you please provide some kind of written reference to start digging deeper? Jul 5, 2018 at 12:51
  • You might want to look at GObject as a good reference implementation. Jul 5, 2018 at 15:09
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.

8
  • 2
    This isn't necessarily a problem. Some languages provide other mechanisms (non-virtual methods in C++ and C#) for accomplishing the same thing intentionally - C# even provides "sealed" methods to further extend this idea! Obviously, you wouldn't do this just for the heck of it, but it's a good technique to be aware of...
    – Shog9
    Aug 2, 2011 at 23:50
  • @Steve, that is not replacing, as you can still call both methods directly.
    – user1249
    Aug 3, 2011 at 9:49
  • @Steve, in Java static methods cannot be overridden.
    – user1249
    Aug 3, 2011 at 21:26
  • @Thorbjørn - first, the question isn't tagged Java, or any other specific OOP language. More importantly, I didn't say you could override a static member function. I was trying to use an analogy to make a point. As I clearly failed, comments deleted.
    – user8709
    Aug 3, 2011 at 21:47
  • 2
    In a sense, these are still "new implementations of methods". Just not in the standard OOP sense. This feels a bit like I'm saying "your wording ain't perfect either, nur-nur-na-nur-nur" ;-)
    – user8709
    Aug 3, 2011 at 21:59
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)

5
  • 1
    I thin the OP understands what static means, he is asking why not just declare everything as static.
    – Ed S.
    Aug 2, 2011 at 23:31
  • 1
    He is passing in an instance of Subject - but as an explicit parameter, instead of the implicit this parameter.
    – user8709
    Aug 2, 2011 at 23:33
  • Well, yeah... but I don't see your point I suppose.
    – Ed S.
    Aug 2, 2011 at 23:35
  • @Ed - only that you can do pretty much anything through an explicit parameter that you could through an implicit this parameter. There's differences in expectations, but outside of inheritence, there's no real difference in what you can do. For example, those non-static members can be accessed - via the explicit parameter.
    – user8709
    Aug 2, 2011 at 23:59
  • I was operating under the assumption that you could not get at private members of the argument in C# even through a static method declared in the same class (as you can in C++). Not sure why I thought that, but I was wrong.
    – Ed S.
    Aug 3, 2011 at 0:26
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.

2
  • 1
    Your statement "...is a throwback to procedural programming..." makes me think that you consider it so bad, I guess it is part of OO in a sense.
    – NoChance
    Feb 29, 2012 at 10:00
  • making ... unit testing much easier. No it won't. It makes it makes any code that calls static methods impossible to unit test, since you can't isolate it from the static method. A call to a static method becomes a hardcoded dependency to that class.
    – StuperUser
    Dec 19, 2012 at 13:21
3

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.

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.

3
  • 4
    You might do it if you were passing an object to a static method, and returning a new object. Functional programmers do this all the time. Aug 3, 2011 at 3:50
  • question: do you consider the Math static class "complex for no gain", or would you prefer it if all number types had virtual methods defining absolute value, negation, adding, squaring, arbitrary roots and so on? I don't think so. objects are neat when you need to store hidden mutable state where you need to enforce some invariants. mashing together every concievable method that operates on a type into the type itself, THAT is something that leads to complex and unmaintainable code. I agree with Robert, you might wanna look at how functional programmers work, it can be a real eye-opener!
    – sara
    Jun 28, 2016 at 15:27
  • @kai As I said, pretty much. The Math class is a reasonable exception, although attaching it to the numeric types wouldn't be a bad idea. Jun 28, 2016 at 21:36
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).

1
  • Since the static method in question requires an instance of the class. I think your assessment of not having to create an instance to call the static method is incorrect... The entire "devil's advocate" argument falls apart once this is accounted for.
    – Daniel T.
    Oct 26, 2021 at 23:17
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.

-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...

1
  • 2
    How does this static method hiding and where would this difference and problem emerge when extending the class? How does synchronized fit in with this? Where do the problems of static and inheritance be encountered? Can you provide some good and bad of static methods in the core Java libraries and explain why each is the case?
    – user40980
    Jun 17, 2015 at 16:14

Not the answer you're looking for? Browse other questions tagged or ask your own question.