Fog Creek Software
Discussion Board




uses of static

For some reason I can't get my brain around this. What are the differences between the following two examples? When would you use one over the other? Is the end result the same?

1st Example
------------------
public class A
{
    static B myB;

    public void DoSomething
    {
          myB.DoSomething()
    }
}

public class B
{
    private B(){}
    public void DoSomething(){}
}
------------------

2nd Example
------------------
public class A
{
    public A(){}

    public void DoSomething
    {
          B.DoSomething()
    }
}

public class B
{
    public static B(){}
    public static void DoSomething(){}
}

DownySoft
Thursday, May 29, 2003

public class A
{
    static B myB; // class variable; can be referenced without an instance of A

    public void DoSomething
    {
          myB.DoSomething(); // NullPointerException - myB doesn't point to any object
    }
}

public class B
{
    private B(){}
    public void DoSomething(){}
}

2nd Example
------------------
public class A
{
    public A(){}

    public void DoSomething
    {
          B.DoSomething(); // fine because DoSomething is static; instance of B isn't required
    }
}

public class B
{
    public static B(){} // illegal - static can't be used with CTORs
    public static void DoSomething(){}
}

M Evelyn
Thursday, May 29, 2003

Yes they are the same: both wrong.

First, the declaration of the method DoSomething() lacks a pair of ().

Second, in the first example, myB cannot be instantiated
due to the private constructor. Hence          myB.DoSomething() will fail because myB is still null. (No new() called anyway. )

Third, in the second example, the constructor B() cannot be static. It doesn't make sense and won't compile.

Maybe you were trying to instantiate a B object as a class variable shared by all A objects in the first example. And in the next, you were trying to make a non-instantiable class B. If this is what you are asking. Yes they are different.

This really sounds like an Intro. to OOP assignment 2 to me. So maybe I will just stop here. :)

S.C.
Thursday, May 29, 2003

Static methods can't touch this.

Alyosha`
Thursday, May 29, 2003

The real difference is in scope.

Your own particular combinations make very little difference, but there are combinations that are important.

If you make doSomething a static member of B and B is public that means that any class that imports B can used doSomething with B.doSomething().

If myB is a static member of A and myB is private, then only A can access myB.doSomething().

Don't try to understand the whole Static and Scope issue from a technical point of view.  What you are really dealing with is encapsulation. 

You would use B.doSomething() if you wanted a function to be easily available anywhere.  Take a look at java.math for examples of this.

You would use private static B myB when you want B to be shared within a restricted scope.

Ged Byrne
Thursday, May 29, 2003

"Third, in the second example, the constructor B() cannot be static. It doesn't make sense and won't compile."

Actually, .NET has the concept of static constructors (also called "class constructors"). Internally, constructors are named ".ctor" and class constructors are named ".cctor". There can be only one static constructor, and it must take no parameters. It is called just before the first access of any static method or data, and are used to initialize static data.

In fact, writing this class:

public class Foo
{
  static private Bar myBar = new Bar(42);
}

impliticly creates a static constructor. If you explicitly create a static constructor as well, all these "implicit" lines of static constructor code are inserted at the beginning of the static constructor method body.

Brad Wilson (dotnetguy.techieswithcats.com)
Thursday, May 29, 2003

"It is called just before the first access of any static method or data."

Eek! Sounds like VB's "Dim ... As New" all over again. That's going to make maintenance programming a pain ... you'll have to hunt down the first reference of where a static method / property on the class is called (which could be anywhere in the code) if you spot a bug in the static constructor. Or am I missing something?

Better Than Being Unemployed...
Thursday, May 29, 2003

I actually don't know what you're saying.

Are you saying that you thing debugging a static constructor is difficult? Why do you suppose that is, when it's just another method?

Brad Wilson (dotnetguy.techieswithcats.com)
Thursday, May 29, 2003

Java has the same feature:

http://www.fawcette.com/javapro/2003_04/online/tricks_pford_04_10_03/

I've never heard of it being a maintenance nightmare.  As far as I know it solves a few maintenance problems.

Ged Byrne
Thursday, May 29, 2003

First of all (pet peeve), "static constructors" in .NET aren't any more new and innovative than metadata in java - java called them static initializers instead of static constructors, and C# called them attributes instead of metadata, but it's the same thing.  Not really any more or less difficult to debug, although it can get a little annoying cause the possible "callers" of a static constructor aren't as obvious.

As for the question at hand, there's an interesting difference that I've actually used that no one's pointed out yet.  Not sure how common this is, but here's the basic idea:

Static methods can't be overridden, but instance methods can.  Static methods that delegate to instance methods can end up calling the subclass' implementation.

I have a "QueryUtils" class in my generic utils package, which among other things knows how to format various objects for inclusion in a database query.  I typically use prepared statements so that the driver does this for me, but with in/not in clauses, I sometimes just use the static QueryUtils.format() method.  It handles strings, numbers, booleans, etc., and also handles collections of these by calling format() recursively with the elements of the collection.  Then, I have an application-specific subclass of QueryUtils, which adds support for formatting a few of my application-specific objects.  It checks to see if the formatted object is one of these, and if not, it hands the object off to the superclass for formatting.  However, if someone passes a collection of application-specific objects, I'd like the superclass' format() method to recursively call the subclass' format() method, since the generic QueryUtils class doesn't understand my application-specific objects.

(Yes, this is a real-world example, and real-world examples are sometimes messy.  Sorry.)

There are undoubtedly other ways to do this, some of which may be nicer, but this seemed to fit what I wanted to do the best.

Here's a quick pseudocode sketch of the code:

class QueryUtils {
  static QueryUtils s_me = new QueryUtils();

  public static String format(Object o) {
    return s_me.format(o);
  }

  protected String format(Object o) {
    // format the object, call recursively on each
    // element if o is a container
  }
}

class MyQueryUtils extends QueryUtils {
  static MyQueryUtils s_me = new MyQueryUtils();

  static String format(Object o) {
    return s_me.format(o);
  }

  protected String format(Object o) {
    // if o needs application-specific formatting,
    // format it and return it.  otherwise, call
    // super.format(o);
  }
}

schmoe
Thursday, May 29, 2003

To clarify, the trick in the above pseudocode is that when the superclass' format() method makes a recursive call, it's calling the instance method on "this", which sometimes calls MyQueryUtils' format() method, not the static method, which would always call QueryUtils.format(), regardless of the type of 'this'.

schmoe
Thursday, May 29, 2003

For the record, my brain fell out of my head just after Brad's post.

But I think the real question is; when should you use Static verses a Singleton?

At least, that is what I think he was getting at.

Marc
Thursday, May 29, 2003

"First of all (pet peeve), "static constructors" in .NET aren't any more new and innovative than metadata in java"

My pet peeve back to you: I never claimed their were innovative. I was just pointing out that they're not illegal and impossible by giving an example of one environment that allows them.

~~~

As to the question of when to use static vs. singleton... the answer is that there's no easy answer. One example of why you might want a singleton (or a singleton-acting thing) is what schmoe was saying: overriding methods. As you could see in his example, you don't even have to expose the singleton to the end user, because you hide it behind a purely static facade.

Brad Wilson (dotnetguy.techieswithcats.com)
Thursday, May 29, 2003

Another time you'll need a singleton is when an object is required.  For example, when you need to compare, test for equality or store in a container.

Ged Byrne
Thursday, May 29, 2003

*  Recent Topics

*  Fog Creek Home