Одним из примеров, когда имеет смысл наследование нескольких классов, является шаблон Observer.Этот шаблон описывает двух действующих лиц, наблюдателя и наблюдаемого, и первый хочет получить уведомление, когда последний изменит свое состояние объекта.
Упрощенная версия для уведомления клиентов может выглядеть следующим образом в C #:
public abstract class Observable
{
private readonly List<IObserver> _observers = new List<IObserver>();
// Objects that want to be notified when something changes in
// the observable can call this method
public void Subscribe(IObserver observer)
{
_observers.Add(observer);
}
// Subclasses can call this method when something changes
// to notify all observers
protected void Notify()
{
foreach (var observer in _observers)
observer.Notify();
}
}
По сути, это основная логика, которую вы должны уведомить всех зарегистрированных наблюдателей.Вы можете сделать любой класс наблюдаемым, производным от этого класса, но, поскольку C # поддерживает только наследование одного класса, вы ограничены в том, чтобы не наследовать от другого класса.Как-то так не получится:
public class ImportantBaseClass { /* Members */ }
public class MyObservableSubclass : ImportantBaseClass, Observable { /* Members */ }
В этих случаях вам часто приходится копировать код, который делает подклассы наблюдаемыми во всех из них, в основном нарушая принцип «Не повторяйся» и «Единую точку истины».принципы (если вы делали MVVM в C #, подумайте об этом: как часто вы реализуете интерфейс INotifyPropertyChanged
?).По моему мнению, решение с наследованием нескольких классов будет намного чище.В C ++ приведенный выше пример компилируется просто отлично.
Дядя Боб написал интересную статью об этом , откуда я взял пример.Но эта проблема часто применяется ко всем интерфейсам, которые * могут (например, сопоставимы, уравниваемы, перечислимы и т. Д.): Версия наследования нескольких классов в этих случаях часто чище, как сказал Бертран Мейер в своей книге «Построение объектно-ориентированного программного обеспечения»».