views:

2086

answers:

9

Sorry in advance if the question is naive...

Is there a way of forcing a (child) class to have constructors with particular signatures or particular static methods in C# or Java?

You can't obviously use interfaces for this, and I know that it will have a limited usage. One instance in which I do find it useful is when you want to enforce some design guideline, for example:

Exceptions
They should all have the four canonical constructors, but there is no way to enforce it. You have to rely on a tool like FxCop (C# case) to catch these.

Operators
There is no contract that specifies that two classes can be summed (with operator+ in C#)

Is there any design pattern to work around this limitation? What construct could be added to the language to overcome this limitation in future versions of C# or Java?

+1  A: 

Using generics you can force a type argument to have a parameterless constructor - but that's about the limit of it.

Other than in generics, it would be tricky to actually use these restrictions even if they existed, but it could sometimes be useful for type parameters/arguments. Allowing static members in interfaces (or possibly static interfaces) could likewise help with the "generic numeric operator" issue.

I wrote about this a little while ago when facing a similar problem.

Jon Skeet
A: 

The problem in the language is that static methods are really second class citizens (A constructor is also a kind of static method, because you don't need an instance to start with).

Static methods are just global methods with a namespace, they don't really "belong" to the class they are defined in (OK, they have access to private (static) methods in the class, but that's about it).

The problem on the compiler level is that without a class instance you don't have a virtual function table, which means you cannot use all the inheritance and polymorphism stuff.

I think one could make it work by adding a global/static virtual table for each class but if it hasn't been done yet, there's probably a good reason for it.

TToni
The problem, if you think about it, is "how would you access an overridden static method?". The only way that overriding is ever useful is if you have an object whose class may vary.If you are going to access it through an instance you may as well make it an instance method.
DJClayworth
+2  A: 

Force Constructors

You can't. The closest that you can come is make the default constructor private and then provide a constructor that has parameters. But it still has loopholes.

class Base
{
  private Base() { }
  public Base(int x) {}
}

class Derived : Base
{
  //public Derived() { } won't compile because Base() is private
  public Derived(int x) :base(x) {}
  public Derived() : base (0) {} // still works because you are giving a value to base
}
jop
A: 

Well, I know from the wording of your question you are looking for compile-time enforcement. Unless someone else has a brilliant suggestion/hack that will allow you to do this the way you are implying the compiler should, I would suggest that you could write a custom MSbuild task that did this. An AOP framework like PostSharp might help you accomplish this at comiple-time by piggy backing on it's build task model.

But what is wrong with code analysis or run-time enforcement? Maybe it's just preference and I respect that, but I personally have no issues with having CA/FXCop check these things... and if you really want to force downstream implementers of your classes to have constructor signatures, you can always add rules run-time checking in the base class constructor using reflection.

Richard

ZeroBugBounce
It's more than that: try writing a generic class that as generic type accepts any object that can be summed... There is no "sane" way of doing it. The only way is to define an interface with a "Add" method and require that -- obviously though you have to box ints, doubles etc...
Sklivvz
Re "Add" - yes you can:http://www.pobox.com/~skeet/csharp/miscutil/usage/genericoperators.html
Marc Gravell
+3  A: 

You could use the Factory pattern.

interface Fruit{}

interface FruitFactory<F extends Fruit>{
   F newFruit(String color,double weight);

   Cocktail mixFruits(F f1,F f2);
}

You could then create classes for any type of Fruit

class Apple implements Fruit{}
class AppleFactory implements FruitFactory<Apple>{
   public Apple newFruit(String color, double weight){
       // create an instance
   }
   public Cocktail mixFruits(Apple f1,Apple f2){
       // implementation
   }
}

This does not enforce that you can't create instance in another way than by using the Factory but at least you can specify which methods you would request from a Factory.

jrudolph
A: 

Here is I would solve it if I were a language designer.

Allow interfaces to include static methods, operators and constructors.

interface IFoo  
{  
  IFoo(int gottaHaveThis);  
  static Bar();  
}

interface ISummable
{
      operator+(ISummable a, ISummable b);
}

Don't allow the corresponding new IFoo(someInt) or IFoo.Bar()

Allow constructors to be inherited (just like static methods).

class Foo: IFoo
{
  Foo(int gottaHaveThis) {};
  static Bar() {};
}

class SonOfFoo: Foo 
{
  // SonOfFoo(int gottaHaveThis): base(gottaHaveThis); is implicitly defined
}

class DaughterOfFoo: Foo
{
  DaughhterOfFoo (int gottaHaveThis) {};
}

Allow the programmer to cast to interfaces and check, if necessary, at run time if the cast is semantically valid even if the class does not specify explicitly.

ISummable PassedFirstGrade = (ISummable) 10;
Sklivvz
Which code would you call on IFoo.Bar()? There is a reason why you can't have static methods in interfaces...
TToni
What if you have more than one class that implements ISummable? Which constructor dou you call with (ISummable) 10;
TToni
@Toni, IFoo.Bar() would generate a compile time exception;(ISummable) 10 would not need a constructor. It would generate an exception if "10" does not implement the ISummable contract (i.e. if it doesn't have the operator+ defined.
Sklivvz
A: 

Unfortunately you can't in C#. Here is a punch at it though:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Foo.Instance.GetHelloWorld());
        Console.ReadLine();
    }
}

public class Foo : FooStaticContract<FooFactory>
{
    public Foo() // Non-static ctor.
    {
    }

    internal Foo(bool st) // Overloaded, parameter not used.
    {
    }

    public override string GetHelloWorld()
    {
        return "Hello World";
    }
}

public class FooFactory : IStaticContractFactory<Foo>
{
    #region StaticContractFactory<Foo> Members

    public Foo CreateInstance()
    {
        return new Foo(true); // Call static ctor.
    }

    #endregion
}

public interface IStaticContractFactory<T>
{
    T CreateInstance();
}

public abstract class StaticContract<T, Factory>
    where Factory : IStaticContractFactory<T>, new() 
    where T : class
{
    private static Factory _factory = new Factory();

    private static T _instance;
    /// <summary>
    /// Gets an instance of this class. 
    /// </summary>
    public static T Instance
    {
        get
        {
            // Scary.
            if (Interlocked.CompareExchange(ref _instance, null, null) == null)
            {
                T instance = _factory.CreateInstance();
                Interlocked.CompareExchange(ref _instance, instance, null);
            }
            return _instance;
        }
    }
}

public abstract class FooStaticContract<Factory>
    : StaticContract<Foo, Factory>
    where Factory : IStaticContractFactory<Foo>, new() 
{
    public abstract string GetHelloWorld();
}
Jonathan C Dickinson
A: 

I'm unsure as to what you are trying to achieve, can you please elaborate? The only reason for forcing a specific constructor or static method accross different classes is to try and execute them dynamically at run time, is this correct?

A constructor is intended to be specific to a particular class, as it is intended to initialise the specific needs of the class. As I understand it, the reason you would want to enforce something in a class hierarchy or interface, is that it is an activity/operation relevant to the process being performed, but may vary in different circumstances. I believe this is the intended benefit of polymorphism, which you can't achieve using static methods.

It would also require knowing the specific type of the class you wanted to call the static method for, which would break all of the polymorphic hiding of differences in behaviour that the interface or abstract class is trying to achieve.

If the behaviour being represented by the constructor is intended to be part of the contract between the client of these classes then I would add it explicitly to the interface.

If a hierarchy of classes have similar initialisation requirements then I would use an abstract base class, however it should be up to the inheriting classes how they find the parameter for that constructor, which may include exposing a similar or identical constructor.

If this is intended to allow you to create different instances at runtime, then I would recommend using a static method on an abstract base class which knows the different needs of all of the concrete classes (you could use dependency injection for this).

marcj
A parent class that knows about all its child classes is a huge violation of good OO programming.
DJClayworth
Agreed. I wouldn't like to do this, but then so is forcing the same static methods or constructors on an entire hierarchy. I would only really use the method as a wrapper to an dependency injection framework which loaded the correct class at run time, as a quick implementation of a factory.
marcj
A: 

Not enforced at compile-time, but I have spent a lot of time looking at similar issues; a generic-enabled maths library, and an efficient (non-default) ctor API are both avaiable in MiscUtil. However, these are only checked at first-usage at runtime. In reality this isn't a big problem - your unit tests should find any missing operator / ctor very quickly. But it works, and very quickly...

Marc Gravell