Перегруженные функции с унаследованным параметром - PullRequest
2 голосов
/ 04 марта 2020

Я пытаюсь сделать что-то вроде этого, но у меня появляется ошибка в соответствии с:

Невозможно преобразовать класс AbstractExampleClass в SpecificExampleClassA.

Так что я, вероятно, иду в неправильном направлении с этим кодом, может кто-нибудь сказать мне, что не так и как это исправить.

public abstract class AbstractExampleClass 
{
    // Code goes here
}

public class SpecificExampleClassA : AbstractExampleClass 
{

}

public class SpecificExampleClass : AbstractExampleClass 
{

}

public class handler 
{
    public void Handle(AbstractExampleClass aec)
    {
        HandleSpecific(aec);
    }

    public void HandleSpecific(SpecificExampleClassA a)
    {
        // DoSomething
    }

    public void HandleSpecific(SpecificExampleClassB b)
    {
        // DoSomething Else
    }

}

Ответы [ 3 ]

4 голосов
/ 04 марта 2020

Перегрузка разрешается во время компиляции, поэтому вы не можете ожидать, что она решит, какую перегрузку вызвать, в зависимости от типа времени выполнения из aec. Перегрузка для вызова должна быть решена во время компиляции.

Здесь вам действительно нужен тип полиморфизма " subtyping " (он же просто "полиморфизм" в C# терминология), а не ad ho c полиморфизм (он же «перегрузка»).

Вместо этого переместите методы-обработчики в подклассы:

public abstract class AbstractExampleClass 
{
    public abstract void Specific();
}

public class SpecificExampleClassA : AbstractExampleClass 
{

    public override void Specific()
    {
        // DoSomething
    }
}

public class SpecificExampleClass : AbstractExampleClass 
{

    public override void Specific()
    {
        // DoSomething Else
    }
}

public class handler 
{
    public void Handle(AbstractExampleClass aec)
    {
        aec.Specific();
    }
}
0 голосов
/ 04 марта 2020

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

    public void Handle(AbstractExampleClass aec)
    {
        switch (aec)
        {
            case SpecificExampleClassA a:
                HandleSpecific(a);
                break;
            case SpecificExampleClassB b:
                HandleSpecific(b);
                break;
            default:
                throw new Exception($"What do I do with a '{aec?.GetType()}'?");
        }
    }

Но я рекомендую подход, подобный тому, который приведен в ответе Sweeper, если вам разрешено это делать.

0 голосов
/ 04 марта 2020

Это может быть обработано Шаблон посетителя

public abstract class AbstractExampleClass 
{
    public abstract void Accept( Handler handler );
}

public class SpecificExampleClassA : AbstractExampleClass 
{
    public override Accept( Handler handler )
    {
        handler.HandleSpecific( this );
    }
}

public class SpecificExampleClass : AbstractExampleClass 
{
    public override Accept( Handler handler )
    {
        handler.HandleSpecific( this );
    }
}

public class Handler // the Visitor
{
    public void Handle(AbstractExampleClass aec)
    {
        aec.Accept( this );
    }

    public void HandleSpecific(SpecificExampleClassA a) // visit method
    {
        // DoSomething
    }

    public void HandleSpecific(SpecificExampleClassB b) // visit method
    {
        // DoSomething Else
    }
}
...