tags:

views:

670

answers:

11

I hit this problem all the time. Suppose I am making a command line interface (Java or C#, the problem is the same I think, I will show C# here).

  1. I define an interface ICommand
  2. I create an abstract base class CommandBase which implements ICommand, to contain common code.
  3. I create several implementation classes, each extending the base class (and by extension the interface).

Now - suppose that the interface specifies that all commands implement the Name property and the Execute method...

For Name each of my instance classes must return a string that is the name of that command. That string ("HELP", "PRINT" etc) is static to the class concerned. What I would love to be able to do is define:

public abstract static const string Name;

However (sadly) you cannot define static members in an interface.

I have struggled with this issue for years now (pretty much any place I have a family of similar classes) and so will post my own 3 possible solutions below for your votes. However since none of them is ideal I am hoping someone will post a more elegant solution.


UPDATE:

  1. I can't get the code formatting to work properly (Safari/Mac?). Apologies.
  2. The example I am using is trivial. In real life there are sometimes dozens of implementing classes and several fields of this semi-static type (ie static to the implementing class).

  3. I forgot to mention - ideally I want to be able to query this information statically:

    string name = CommandHelp.Name;

2 of my 3 proposed solutions require that the class be instantiated before you can find out this static information which is ugly.

A: 

[Suggested solution #1 of 3]

  1. Define an abstract property Name in the interface to force all implementing classes to implement the name property.
  2. (in c#) Add this property as abstract in the base class.
  3. In the implementations implement like this:

    public string Name { get {return COMMAND_NAME;} }

    Where name is a constant defined in that class.

    Advantages:

    • Name itself defined as a constant.
    • Interface mandates the property be created.

    Disadvantages:

    • Duplication (which I hate). The exact same property accessor code pasted into every one of my implementations. Why cant that go in the base class to avoid the clutter?
Ewan Makepeace
+2  A: 

You may consider to use attributes instead of fields.

[Command("HELP")]
class HelpCommand : ICommand
{
}
Thomas Danecker
A: 

just add the name property to the base class and pass it ito the base class's constructor and have the constuctor from the derived class pass in it's command name

Bob Dizzle
+1  A: 
public interface ICommand {
      String getName();
}

public class RealCommand implements ICommand {
     public String getName() {
           return "name";
     }
}

Simple as that. Why bother having a static field?


Obs.: Do not use a field in an abstract class that should be initiated in a subclass (like David B suggestion). What if someone extends the abstract class and forget to initiate the field?

Marcio Aguiar
It isn't said in the original question, but s/he wants a field so that s/he can bind to it in WPF.
vanja.
A: 

What I usually do (in pseudo):

abstract class:

private const string nameConstant = "ABSTRACT";

public string Name
{
   get {return this.GetName();}
}

protected virtual string GetName()
{
   return MyAbstractClass.nameConstant;
}

----

class ChildClass : MyAbstractClass
{
   private const string nameConstant = "ChildClass";

   protected override string GetName()
   {
      return ChildClass.nameConstant;
   }
}

Of course, if this is a library that other developers will use, it wouldn't hurt if you add some reflection in the property to verify that the current instance in fact does implement the override or throw an exception "Not Implemented".

Sunny
A: 

[Suggested solution #2 of 3]

  • Make a private member variable name.
  • Define an abstract property Name in the interface.
  • Implement the property in the base class like this:

    public string Name { get {return Name;} }

  • Force all implementations to pass name as a constructor argument when calling the abstract base class constructor:

    public abstract class CommandBase(string commandName) : ICommand { name = commandName; }

  • Now all my implementations set the name in the constructor:

    public class CommandHelp : CommandBase(COMMAND_NAME) {}

Advantages:

  • My accessor code is centralised in the base class.
  • The name is defined as a constant

Disadvantages

  • Name is now an instance variable - every instance of my Command classes makes a new reference rather than sharing a static variable.
Ewan Makepeace
A: 

My answer will relate to Java, as that is what I know. Interfaces describe behavior, and not implementation. Additionally, static fields are tied to the classes, and not instances. If you declared the following:

interface A { abstract static NAME }
class B { NAME = "HELP" }
class C { NAME = "PRINT" }

Then how could this code know which NAME to link to:

void test(A a) {
    a.NAME;
}

How I would suggest to implement this, is one of the following ways:

  • Class name convention, and the base class derives the name from the class name. If you wish to deviate from this, override the interface directly.
  • The base class has a constructor which takes name
  • Use annotations and enforce their presence through the base class.

However, a much better solution is proabably to use enums:

public enum Command {
    HELP { execute() }, PRINT { execute() };
    abstract void execute();
}

This is much cleaner, and allows you to use switch statements, and the NAME will be easily derived. You are however not able to extended the number of options runtime, but from your scenario description that might not be even needed.

Staale
That won't work in C# as you can't declare an abstract member in an interface; otherwise it looks like it would work very well.
Scott Dorman
Again - my example was deliberately simple (one single string) but in reality there are normally 3 or 4 fields that are static to each implementation but vary between classes.
Ewan Makepeace
A: 

[Suggested answer # 3 of 3]

I have not tried this yet and it would not be so nice in Java (I think?) but I could just tag my classes with Attributes:

[CammandAttribute(Name="HELP")]

Then I can use reflection to get that static information. Would need some simple helper methods to make the information easily available to the clients of the class but this could go in the base class.

Ewan Makepeace
+2  A: 

As you mentioned, there is no way to enforce this from the interface level. Since you are using an abstract class, however, what you can do is declare the property as abstract in the base class which will force the inheriting class it override it. In C#, that would look like this:

public abstract class MyBaseClass
{
  public abstract string Name { get; protected set; }
}

public class MyClass : MyBaseClass
{
  public override string Name
  {
    get { return "CommandName"; }
    protected set { }
  }
}

(Note that the protected set prevents outside code changing the name.)

This may not be exactly what you're looking for, but it's as close as I think you can get. By definition, static fields do not vary; you simply can't have a member that is both static and overridable for a given class.

Jeromy Irvine
A: 

From a design perspective, I think it is wrong to require a static implementation member... The relative deference between performance and memory usage between static and not for the example string is minimal. That aside, I understand that in implementation the object in question could have a significantly larger foot print...

The essential problem is that by trying to setup a model to support static implementation members that are avaialble at a base or interface level with C# is that our options are limited... Only properties and methods are available at the interface level.

The next design challenge is whether the code will be base or implementation specific. With implementation your model will get some valdiation at compile time at the code of having to include similar logic in all implementations. With base your valdiation will occur at run time but logic would be centralized in one place. Unfortunately, the given example is the perfect show case for implemntation specific code as there is no logic associated with the data.

So for sake of the example, lets assume there is some actual logic associated with the data and that it is extensive nad/or complex enough to provide a showcase for base classing. Setting aside whether the base class logic uses any impelementation details or not, we have the problem of insuring implemtation static initialization. I would recommend using an protected abstract in the base class to force all implementations to created the needed static data that would be valdated at compile time. All IDE's I work with make this very quick any easy. For Visual Studio it only takes a few mouse clicks and then just changing the return value essentially.

Circling back to the very specific nature of the question and ignoring many of the other design problems... If you really must keep this entire to the nature of static data and still enforce it thru the nature confines of the problem... Definately go with a method over properties, as there are way to many side effects to make go use of properties. Use a static member on the base class and use a static constructor on the implementations to set the name. Now keep in mind that you have to valdiate the name at run-time and not compile time. Basically the GetName method on the base class needs to handle what happens when an implementation does not set it's name. It could throw an exception making it brutally apparent that something is worng with an implementation that was hopefulyl cause by testing/QA and not a user. Or you could use reflection to get the implementation name and try to generate a name... The problem with reflection is that it could effect sub classes and set up a code situation that would be difficult for a junior level developer to understand and maintain...

For that matter you could always generate the name from the class name thru reflection... Though in the long term this could be a nightmare to maintain... It would however reduce the amount of code needed on the implementations, which seems more important than any other concerns. Your could also use attributes here as well, but then you are adding code into the implementations that is equivalent in time/effort as a static constructor and still have the problem off what todo when the implementation does not include that information.

Shire
A: 

What about something like this:

abstract class Command {
   abstract CommandInfo getInfo();
}

class CommandInfo {
  string Name;
  string Description;
  Foo Bar;
}

class RunCommand {
  static CommandInfo Info = new CommandInfo() { Name = "Run", Foo = new Foo(42)  };

  override commandInfo getInfo() { return Info; }
}

Now you can access the information statically:

RunCommand.Info.Name;

And from you base class:

getInfo().Name;
Hallgrim