переопределение абстрактного универсального метода из неуниверсального класса - PullRequest
5 голосов
/ 08 февраля 2012

базовый класс

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

производный класс # 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
    }
}

производный класс # 2

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

Ошибка в производном классе # 1:«не найдено подходящего метода для переопределения»

Должен ли я использовать «виртуальный» в базовом классе, а также «абстрактный»?

Как установить базовый класстип параметра, чтобы разрешить множество параметров в производных классах?

Ответы [ 3 ]

8 голосов
/ 08 февраля 2012

Ваш код имеет больше проблем, чем тот, о котором вы спрашиваете. Отложив вопрос переопределения на данный момент, класс ADrawer нуждается в ограничении типа (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 
    } 
} 

Без этого ограничения недопустимо передавать a в DrawA, поскольку a является ссылкой типа T, а без ограничения не существует неявного преобразования из типа T в тип Agent.

Класс AnotherDrawer незаконно использует оператор ==. Невозможно применить оператор == к операндам типа T и int. Вы можете обойти это, используя переопределение object.Equals.

Наконец, у базового класса есть ошибка, потому что это неабстрактный класс, содержащий абстрактный член.

Однако в целом этот код указывает, что класс должен быть универсальным, а не метод :

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

производный класс # 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
    }
}

производный класс # 2

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

Чтобы прокомментировать комментарий Эрика Липперта, который также был моей первой реакцией на ваш вопрос, вы можете рассмотреть этот вариант:

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

производный класс # 1

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

Производный класс # 2 не изменяется.

5 голосов
/ 08 февраля 2012

абстрактный метод должен иметь эту подпись

  public abstract void Draw<T>(List<T> type);  
1 голос
/ 08 февраля 2012

Чтобы получить его для компиляции, измените базовый класс на следующий:

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

List<T> не совпадает с T, поэтому при передаче List<T> в производный класс 'метод, который нельзя переопределить базовым методом, так как он имеет параметр T, а не параметр List<T>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...