Ще в 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контексті.