C # Абстрактная функция с реализацией возможно? - PullRequest
10 голосов
/ 22 июля 2011

Есть ли способ добавить виртуальную функцию, которая должна быть переопределена всеми унаследованными классами? Так на самом деле сочетание виртуального и абстрактного? У меня есть ситуация, когда каждый унаследованный класс должен выполнить определенную обработку перед выполнением некоторого универсального кода. Виртуальные функции не работают, потому что они не гарантируют, что унаследованные классы переопределят их. И абстрактная функция не может иметь реализацию по умолчанию. В настоящее время мой обходной путь заключается в реализации другой защищенной функции в базовом классе, которая содержит общий / общий код и вызывается в переопределенной абстрактной функции

Ответы [ 3 ]

14 голосов
/ 22 июля 2011

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

Если возможно, вы можете разделить ваш метод на части «до» и «после»:

public void DoWork()
{
    DoBeforeWork();
    DoCommonWork();
    DoAfterWork();
}

protected abstract void DoBeforeWork();
protected abstract void DoAfterWork();

private void DoCommonWork() { ... }

В противном случае ваш обходной путь со вторым защищенным методом - очень хорошая идея:

public void DoWork()
{
    DoActualWork();
}

protected abstract void DoActualWork(); // expected to call DoCommonWork

protected void DoCommonWork() { ... }

Вы можете проверить, действительно ли DoCommonWork вызывался в DoWork, при необходимости используя локальное поле потока.

Однако я бы, вероятно, пошел с тем, чтобы сделать метод виртуальным. Если производный класс не хочет ничего добавлять к общей части, он не должен:

public virtual void DoWork() { ... }

Опять же, вы можете проверить, действительно ли была названа общая часть.

3 голосов
/ 22 июля 2011

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

0 голосов
/ 22 июля 2011

Я предлагаю разделить базовый класс на два: классы один абстрактный и один конкретный запечатанный.

Пример

Я предполагаю, что у вас есть базовый класс, который выглядит так:

public class BaseClass
{
    public void DoProcessing()
    {
        // this method must be overriden in each subclass
    }
}

Давайте разделим это на два:

public abstract class BaseClass
{
    protected abstract DoProcessingImlementation();    

    public void DoProcessing()
    {
        // here you can add program logic or just call overridden implementation
        DoProcessingImplementation();
    }
}

public sealed class DefaultBaseClassImplementation : BaseClass
{
    public override DoProcessingImlementation()
    {
        // default implementation of method
    }
}

С этим дизайном, если вам нужно реализовать новую логику обработки, вы наследуете новый класс от BaseClass, и, поскольку он абстрактный, вы должны реализовать метод DoSomethigImplementation. Чтобы получить доступ к логике обработки по умолчанию, вы должны использовать экземпляр класса DefaultBaseClassImplementation. А то, что DefaultBaseClassImplementation запечатано, не позволит вам наследовать от неправильного класса.

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