Частичные классы / частичные методы против базовых / унаследованных классов - PullRequest
3 голосов
/ 13 января 2010

вопрос о классе дизайна. В настоящее время у меня есть следующая структура:

абстрактный базовый репозиторий класса

Класс реализации репозитория по умолчанию (реализует некоторые абстрактные методы, где логика является общей для всех классов Specific, но оставляет другие пустыми)

Определенный класс реализации репозитория (реализует то, что осталось пустым в вышеуказанном классе по умолчанию)

Теперь я столкнулся с проблемой, когда у меня есть определенный метод Update () в классе Specific, но когда весь код в этом методе выполняет некоторый код из базового класса Default, он также должен быть выполнен.

Я мог бы сделать это так

public override Update()
{
    // do Specific class actions and updates
    // ....

    // follow with base.Update()
    base.Update();
}

но для этого требуются вызовы base.XYZ () во всех унаследованных методах. Могу ли я обойти это как-то с частичным?

Таким образом, требование состоит в том, чтобы иметь код как в родительском, так и в унаследованном классе (или сделать эти два класса одним, используя партиалы), и код из реализации метода в обоих местах должен выполняться. А что если я захочу перевернуть его и сначала выполнить код базового класса, а затем унаследованный код класса?

спасибо

Ответы [ 5 ]

8 голосов
/ 13 января 2010

Рассматривали ли вы что-то вроде:

public abstract class YourBaseClass
{
    public void Update()
    {
        // Do some stuff
        //

        // Invoke inherited class's  method
        UpdateCore();
    }

    protected abstract void UpdateCore();
}

public class YourChildClass : YourBaseClass
{
     protected override void UpdateCore()
     {
         //Do the important stuff
     }
}


//Somewhere else in code:
var ycc = new YourChildClass();
ycc.Update();
3 голосов
/ 13 января 2010

Все ключевое слово partial означает, что определение класса разбито на исходные файлы:

Можно разделить определение класса или структуры, интерфейса или метода на два или более исходных файла. Каждый исходный файл содержит раздел определения типа или метода, и все части объединяются при компиляции приложения.

В проекте все еще должно быть полное определение класса.

Было бы лучше создать подкласс, чтобы вы могли переопределять определенные методы.

Что касается частичных методов (по той же ссылке, что и выше):

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

// Definition in file1.cs
partial void onNameChanged();

// Implementation in file2.cs
partial void onNameChanged()
{
  // method body
}

Нельзя использовать половину метода в одном файле, а другую половину в другом.

2 голосов
/ 13 января 2010

Вот как вы можете это сделать:

public sealed override void Update()
{
    UpdateCore();
    base.Update();
}

public abstract /* or virtual */ void UpdateCore()
{
    // Class-specific stuff
}
1 голос
/ 13 января 2010

Забудьте о частичном, который имеет совершенно другую семантику.То, должен ли переопределитель вашего метода виртуального базового класса вызывать метод базового класса, не является автоматическим.Это должно быть частью вашей документации.Хорошим примером являются методы OnXxxx () в классе Control, в документах библиотеки MSDN есть комментарий «Примечание для разработчика», предупреждающий о том, что вызов метода базового класса обычно необходим.Метод абстрактный, то кристально чистый для переопределителя.Если это не так, вы даете сильный намек на то, что это должно быть сделано.Если вы ожидаете, что переопределение полностью заменит базовую реализацию, вам следует подумать о том, чтобы сделать ее абстрактной.Эта двусмысленность в сочетании с вероятностью того, что переопределитель нарушает ваш базовый класс неправильной переопределением, безусловно, является одним из слабых мест полиморфизма.

0 голосов
/ 13 января 2010

Добавьте новый виртуальный (не абстрактный, так как не все конкретная реализация должна переопределить его?) Метод в реализацию по умолчанию, чтобы приспособить наследников, имеющих свои собственные дополнительные шаги поверх собственной реализации.

Вызовите виртуальный метод в соответствующей точке в реализации абстрактного метода Реализации по умолчанию.

Вы оставили свой абстрактный класс таким, какой он есть, и прозрачно увеличили гибкость реализации по умолчанию.

...