views:

32

answers:

2

I have the following setup (simplified, obviously):

An abstract class, with an A object and an abstract method

abstract public class X
{
    protected A myA;
    abstract public int MethodForX();
}

Two inheriting classes, each of which override the method. However instead of using an A object they use a B and C object, each of which inherit from A.

public class Y : X
{
    public Y()
    {
        myA = new myB(); //B inherits from A
    }
    override public int MethodForX()
    {
        return (myA as myB).MethodForB(1);
    }
}

public class Z : X
{
    public Z()
    {
        myA = new myC(); //C inherits from A
    }
    override public int MethodForX()
    {
        return (myA as myC).MethodForC(1, 2);
    }
}

I don't have direct control over A, B and C. (Specifically B and C are two different table adapters, A is their common ancestor, and the MethodForB/C is a GetData method, with different arguments for each.)

I don't like using "as" every time I want to access the field. I'd like for Y and Z to know that the field is of their required class, but restrict that class to an inheritor of the class in X.

Is there a way of doing that, or not, or am I trying to do something horrendous?

+2  A: 

You could use generics.

abstract public class X<T> where T : A
{
    protected T myA;
    abstract public int MethodForX();
}

public class Y : X<B>
{
    public Y()
    {
        myA = new B(); //B inherits from A
    }
    override public int MethodForX()
    {
        return myA.MethodForB(1);
    }
}
Maximilian Mayerl
+2  A: 

You could try generics, although it isn't pretty:

abstract public class X<T> where T : A
{
    protected T myA;
    abstract public int MethodForX();
}

public class Y : X<B>
{
    public Y()
    {
        myA = new B(); //B inherits from A
    }
    override public int MethodForX()
    {
        return myA.MethodForB(1);
    }
}

public class Z : X<C>
{
    public Z()
    {
        myA = new C(); //C inherits from A
    }
    override public int MethodForX()
    {
        return myA.MethodForC(1, 2);
    }
}
Marc Gravell
Hm... I didn't know you could specify an ancestor like that, I like it. I'll give it a shot.
Rawling
OK, I needed a further change: a further abstract class X containing just the abstract method, from which X<T> inherits, so that I can still cast objects using "is X"/"as X" rather than "is X<...>", where I didn't know what ... should be.It's getting a little more convoluted now, but still doing what I want it to from the outside.
Rawling