Ще в 2000-х моїй колезі сказали мені, що це зробити анти-зразком зробити публічні методи віртуальними чи абстрактними.
Наприклад, він вважав такий клас, як недостатньо розроблений:
public abstract class PublicAbstractOrVirtual
{
public abstract void Method1(string argument);
public virtual void Method2(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
// default implementation
}
}
Він заявив, що
- розробник похідного класу, який реалізує
Method1
та переосмислюєMethod2
, повинен повторити перевірку аргументів. - якщо розробник базового класу вирішить додати щось навколо налаштованої частини
Method1
абоMethod2
пізніше, він не може цього зробити.
Натомість мій колега запропонував такий підхід:
public abstract class ProtectedAbstractOrVirtual
{
public void Method1(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
this.Method1Core(argument);
}
public void Method2(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
this.Method2Core(argument);
}
protected abstract void Method1Core(string argument);
protected virtual void Method2Core(string argument)
{
// default implementation
}
}
Він сказав мені, що публічні методи (або властивості) віртуальними чи абстрактними є такими ж поганими, як і оприлюднення полів. Вставляючи поля у властивості, можна перехопити будь-який доступ до цих полів пізніше, якщо потрібно. Це ж стосується публічних віртуальних / абстрактних членів: обведення їх так, як показано в ProtectedAbstractOrVirtual
класі, дозволяє розробнику базового класу перехоплювати будь-які виклики, що переходять до віртуальних / абстрактних методів.
Але я не розглядаю це як керівництво дизайном. Навіть Microsoft не дотримується цього: просто подивіться на Stream
клас, щоб перевірити це.
Що ви думаєте про цю інструкцію? Це має сенс, чи ви вважаєте, що це надмірно ускладнює API?
protected
найкорисніше, коли ви хочете виставити приватних членів абстрактного класу похідним класам. У будь-якому випадку, я не особливо переймаюся думкою твого друга; виберіть модифікатор доступу, який має найбільш сенс для вашої конкретної ситуації.
virtual
дозволяють необов'язково переосмислити Ваш метод, мабуть, повинен бути загальнодоступним, тому що він може не перекрити. Виготовлення методівabstract
змушує вас їх перекрити; вони, мабуть, повинні бутиprotected
, тому що вони не особливо корисні вpublic
контексті.