0

If you have a Point3 class and have a method called Distance, should you have it static like this:

Point3.Distance ( p1, p2 );

or an instance method like:

this.Distance ( p );

I realize using static methods hinders inheritance and overriding, right?

Which one is better, and why?

Joan Venge
  • 315,713
  • 212
  • 479
  • 689

4 Answers4

5

I prefer the static version. (And this is what we've done across the board in SlimDX, save for a few "special" operations.) The reasoning is that Distance is conceptually a function that processes two points, and has a result. You're not running the "Distance" operation on p1, with p2 as the value.

In short, I prefer that instance methods are conceptually an operation bound to a specific instance. For some, it goes either way. For example, SlimDX includes both static and non static versions of the Vector3 Normalize function, because both constructs are pretty handy. The instance one modifies its object, and the static one returns a new one.

[Edit] Another answer mentions a "DistanceTo" function that would be an instance function. While that's not necessarily unreasonable, it's a design direction that makes me uneasy. The problem is orthogonality. Once you add more of these overloads -- some static, some instance, maybe some in a MathHelper class, who knows -- you end up with more and more ways to do the same thing. This is bad news for library complexity, test complexity, bug surface area, etc. We've chosen to do it in places in SlimDX, but that's in just a select few places across a lot of classes (and every single one's been team reviewed). It can help usability of a library to an extent, but it's really dangerously easy to end up on the wrong side of the line.

Promit
  • 3,497
  • 1
  • 20
  • 29
1

I prefer the static version, but depending on how you use it or expect it to be used, I'd consider including an instance method DistanceTo that calls the static method. Sometimes instance methods like that can make code more concise and readable.

One big selling point frequently for static methods like this is that they can return results even when one or both of their operands is null. If you've only got an instance method, you'll need to test it for null before calling the method. Object.Equals/ReferenceEquals is a canonical example of this.

mqp
  • 70,359
  • 14
  • 95
  • 123
1

"Which one is better?" is a question that largely depends on specific scenario. In some cases you may want static methods, in other cases instance methods, sometimes both. Rather than trying to provide an absolute edict, here are some of my thoughts on how to make this decision.

Clarity Considerations

Static methods can be used when it would be awkward to use an instance of an object. For example, the .NET string class has String.Concat( ) which can concatenate multiple strings.

It is clear to have: String.Concat( "A", "B" ); It's awkward to have: "A".Concat( "B" );

Sometimes it is clearer to provide a name for an operation rather than encoding it as a constructor overload. Int.Parse( ) is a good example. Int could have a constructor that takes a string, but it is unclear what the intent is. The static Parse() method adds clarity.

Maintainability Considerations

Sometimes you have no choice but to implement a function as a static utility method. It may be impossible to add new methods to the class - you may not have the source code, you may wish to avoid testing impacts, etc.

Even when you can add an instance method, it may be useful to de-clutter a class by implementing infrequent or special-purpose methods in utility classes. You should only do this, however, when you can implement the utility class using only the public interface of the type you are extending. In C# 3.5 you can use extension methods to create the illusion that the utility methods are instance methods of the class.

Polymorphism Considerations

If a function is likely to be overridden in a derived type, you should make it an instance member and mark it with the virtual keyword. Instance methods not marked virtual are no more extensible than static methods.

Best Practice Considerations

Static functions should (generally) have no side effects. In other words, they should not modify the state of either of their parameters. Functions that have side effects are best implemented as instance methods of an object.

In OOP there is the single responsibility principle (SRP), which basically states that "every class should only have one reason to change." If adding an instance method to a particular class would violate the SRP, consider factoring that logic out of the class.

Usability Considerations

Sometimes a design goal of your code (particularly framework level code) is usability. In such cases it may be useful to provide both an instance and a static version of a function. However, in such cases it is highly advisable that the instance version be implemented as a call to the static version. This approach allows the consumer of the class to decide which makes sense. An example of this approach is the string.Compare() and string.CompareTo() methods - the former is static while the later is an instance method. This allows the string class to conform to a particular interface (IComparable) while also providing a nice syntax: string.Compare( "A", "a" ).

LBushkin
  • 129,300
  • 32
  • 216
  • 265
0

I prefer instance methods. I want to be able to say

myPoint.distanceTo(another);

This may sound silly, but the fact that I have a neat, memorable name ready for the other element, "that", is part of what inclines me to this preference:

double distanceTo(Point that) {
    double dx = this.x - that.x;
    double dy = this.y - that.y;
    return Math.sqrt(dx^2 + dy^2);
}

(pardon my Java; I'm sure the C# isn't much different). "this" and "that" just work together very nicely and I think make the code more understandable than, say, "a" and "b" would be. Also if it's an instance method, then from my other instance methods, I can use distanceTo() without passing this explicitly.

Carl Manaster
  • 39,912
  • 17
  • 102
  • 155
  • 2
    Hang on. So you're designing the interface to use instance methods because the *implementation* seems nice? You'll understand if I'm dubious. – Promit May 01 '09 at 22:24
  • It's a good point. Erm, no pun intended. Not really _because_, but the nice implementation leaves me feeling good about the interface design. I share your discomfort with my rationale, but - it's how I feel about it. Good interfaces leave me feeling good about the implementations. – Carl Manaster May 01 '09 at 22:29
  • 1
    I give a thumb up for that answer for two reasons. 1. Elegant/Intuitive code usually follows best practices even if u didn't notice or didn't plan for that. Plus, It isn't simple to write elegant & intuitive code unless you are a good developer. 2. I think a static method should be used in certain/limited cases. Static method sounds like general & public service for who's interested to have such service. – Wahid Shalaly Apr 07 '10 at 14:38