W 2000 roku mój kolega powiedział mi, że to anty-wzorzec, aby publiczne metody były wirtualne lub abstrakcyjne.
Na przykład uważał taką klasę za niezbyt dobrze zaprojektowaną:
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
}
}
Stwierdził to
- twórca klasy pochodnej, która implementuje
Method1
i zastępuje,Method2
musi powtórzyć sprawdzanie poprawności argumentów. - na wypadek, gdyby twórca klasy podstawowej zdecydował się dodać coś wokół dostosowywalnej części
Method1
lubMethod2
później, nie może tego zrobić.
Zamiast tego mój kolega zaproponował takie podejście:
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
}
}
Powiedział mi, że upublicznianie publicznych metod (lub właściwości) jest tak samo złe, jak upublicznianie pól. Dzięki zawijaniu pól we właściwości można w razie potrzeby przechwycić później dostęp do tych pól. To samo dotyczy publicznych wirtualnych / abstrakcyjnych członków: zawijanie ich w sposób pokazany w ProtectedAbstractOrVirtual
klasie pozwala programistom klasy podstawowej przechwytywać wszelkie wywołania, które przechodzą do metod wirtualnych / abstrakcyjnych.
Ale nie uważam tego za wytyczne projektowe. Nawet Microsoft tego nie przestrzega: wystarczy spojrzeć na Stream
klasę, aby to sprawdzić.
Co sądzisz o tej wytycznej? Czy to ma sens, czy uważasz, że to komplikuje API?
protected
jest najbardziej przydatny, gdy chcesz narazić prywatnych członków klasy abstrakcyjnej na klasy pochodne. W każdym razie nie martwię się szczególnie o opinię twojego przyjaciela; wybierz modyfikator dostępu, który najlepiej pasuje do konkretnej sytuacji.
virtual
pozwalają na opcjonalne zastąpienie. Twoja metoda powinna być prawdopodobnie publiczna, ponieważ może nie zostać zastąpiona. Tworzenie metodabstract
zmusza do ich przesłonięcia; prawdopodobnie powinnyprotected
, ponieważ nie są szczególnie przydatne wpublic
kontekście.