Question

I'm writing an SDK which has an OOP structure for implementing data types;

  1. first an interface
  2. then an abstract implementation
  3. finally an abstract generic implementation

People can choose to implement either the interface, or derive from either of the classes.

public interface IGoo
{
  IGoo Duplicate();
  ...
}
public abstract class Goo : IGoo
{
  IGoo IGoo.Duplicate() {
    return Duplicate();
  }
  abstract public Goo Duplicate();
  ...
}
public abstract class Goo<T> : Goo
{
  abstract public Goo<T> Duplicate(); ??????
  ...
} 

I'd like to re-implement the Duplicate method so that it always returns the most specific type possible. I.e. when you call Duplicate on an IGoo instance, you get another IGoo. If you call it on Goo, you get Goo, if you call it on -say- Goo<int>, you get Goo<int>. And all Duplicate() methods always call the most specific implementation.

Is this possible? Is it only possible when you can implement an interface explicitly? In which case, should I not make Goo<int> derive from Goo, but have it implement IGoo instead and type all the low-level functionality twice?

Was it helpful?

Solution

What about the following?

public interface IObj
{
    IObj Duplicate();
}

public abstract class Obj : IObj
{
    public Obj()
    {

    }
    public virtual IObj Duplicate()
    {
        return this;
    }
}

public abstract class ObjT<T> : Obj
{
    public ObjT()
    {

    }
    public override IObj Duplicate()
    {
        return this;
    }
}

public class ObjImpl : Obj
{

}

public class ObjTImpl : ObjT<int>
{

}

I understand that you want it to return the most specific type possible in any inheriting class but it actually is. It's boxing the inheriting type into the interface (or a raw object if you where to return objects instead of interface types. If you run the following test in a console app you will see the proper type is represented:

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            ObjImpl a = new ObjImpl();

            ObjTImpl b = new ObjTImpl();

            Console.WriteLine(a.Duplicate().GetType());
            Console.WriteLine(b.Duplicate().GetType());

            Console.ReadLine();
        }
    }
}

// outputs:

// ObjImpl
// ObjTImpl

The idea of redefining abstracts of abstracts goes against the purpose of abstract polymorphism. If the derived types do not intend to implement the inherited abstract member, they should not be inheriting it.

Although the example I gave above would require casting to access any child class-specific members, it would be the proper way to do it in this approach. The runtime needs to know what types it should expect to deal with.

There is always dynamics you could play around with but to be honest I haven't played around with dynamics with generics and inheritance as I suspect I would make my compiler cry, and when it cries, I cry, a little bit deep down inside... lol

OTHER TIPS

It is only possible when you implement the interface explicitly. That's because the return type of a method is not part of its signature - which the compiler checks when overloading. Therefore, otherwise identical methods which only differ in their return type are syntactically not possible.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top