Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

overriding abstract generic method from non generic class

base class

class Drawer
{
    public abstract void Draw<T>(T type);    
}

derived class #1

class ADrawer : Drawer
{
    public override void Draw<T>(List<T> list)
    {
        foreach (var a in list)
        {
            DrawA(a);
        }
    }

    public void DrawA(Agent a)
    {
        //draw code here
    }
}

derived class #2

class AnotherDrawer : Drawer
{
    public override void Draw<T>(T number)
    {
        if (number == 1)
        {
            //draw code
        }
    }
}

The error is in the #1 derived class : "no suitable method found to override"

Should I be using 'virtual' in the base class as well as 'abstract' ?

How should I set the base parameter type to allow a variety of parameters in derived classes?

like image 582
Whiplash450 Avatar asked Feb 08 '12 16:02

Whiplash450


2 Answers

Your code has more problems than just the one you ask about. Setting aside the override question for the moment, class ADrawer needs a type constraint (where T : Agent):

class ADrawer : Drawer 
{ 
    public void Draw<T>(List<T> list) where T : Agent
    { 
        foreach (var a in list) 
        { 
            DrawA(a); 
        } 
    }
    public void DrawA(Agent a) 
    { 
        //draw code here 
    } 
} 

Without that constraint, it's not legal to pass a to DrawA, because a is a reference of type T, and without the constraint there is no implicit conversion from type T to type Agent.

The AnotherDrawer class has an illegal use of the == operator. It's not possible to apply the == operator to operands of type T and int. You could get around that by using the object.Equals override.

Finally, the base class has an error because it is a non-abstract class containing an abstract member.

In general, however, this code indicates that the class should be generic, rather than the method:

abstract class Drawer<T>
{
    public abstract void Draw(T type);
}

derived class #1

class ADrawer : Drawer<List<Agent>>
{
    public override void Draw(List<Agent> list)
    {
        foreach (var a in list)
        {
            DrawA(a);
        }
    }       

    public void DrawA(Agent a)
    {
        //draw code here
    }
}

derived class #2

class AnotherDrawer : Drawer<int>
{
    public override void Draw(int number)
    {
        if (number == 1)
        {
            //draw code
        }
    }
}

To follow up on Eric Lippert's comment, which was also my first reaction to your question, you might consider this design instead:

abstract class Drawer<T>
{
    public abstract void Draw(T type);
    public void DrawMany(IEnumerable<T> types)
    {
        foreach (var t in types)
            Draw(t);
    }
}

derived class #1

class ADrawer : Drawer<Agent>
{
    public override void DrawA(Agent a)
    {
        //draw code here
    }
}

Derived class #2 is unchanged.

like image 77
phoog Avatar answered Nov 15 '22 16:11

phoog


abstract method should have this signeture

  public abstract void Draw<T>(List<T> type);  
like image 34
wiero Avatar answered Nov 15 '22 15:11

wiero