Che cosa significa separare l'interfaccia dall'implementazione in C ++? E anche cosa implica l'interfaccia e l'implementazione?
Che cosa significa separare l'interfaccia dall'implementazione in C ++? E anche cosa implica l'interfaccia e l'implementazione?
Significa che dovresti usare gli oggetti attraverso le classi di interfaccia (puro virtuale) invece delle classi concrete. Questo ti permetterà di cambiare la classe concreta mantenendo intatto il resto del codice (utile per refactoring, testing, ecc.)
Ad esempio se hai un'interfaccia
class INotify
{
public:
virtual void Notify() = 0;
};
Quindi, quando il tuo notificatore lo usa:
class Notifier
{
// ...
void Subscribe(INotify* subscriber)
{
m_subscribers.push_back(subscriber);
}
void NotifyAll()
{
for(auto it = m_subscribers.begin(); it != m_subscribers.end(); ++it)
{
(*it)->Notify();
}
}
// ...
}
Si noti come il Notifier non è accoppiato a una specifica implementazione di classe? Funzionerà qualsiasi classe che implementa INotify
. Questo ti permetterà di usare più di una classe come abbonati, ti permetterà di rifattorizzare i tuoi abbonati senza dover toccare il Notifier e ti permetterà di testare il Notifier deridendo gli abbonati.
E per la tua seconda domanda, l'interfaccia è il contratto pubblico di una classe (le operazioni che puoi fare con essa) e l'implementazione è la realizzazione effettiva di quel contratto (ad esempio una classe di abbonati eredita INotify
e implementa il contratto fornendo la definizione per il metodo Notify
).
Nell'esempio sopra, ho mostrato solo l'interfaccia di INotify
ma non ho mostrato alcuna classe che implementa quell'interfaccia (eredita INotify
e definisco un'implementazione per i metodi puramente virtuali). L'ho fatto apposta perché volevo sottolineare come l'implementazione non sia rilevante per il notificante, ma solo l'interfaccia (contratto) è.
Il termine " interfaccia " è ambiguo nel linguaggio C ++, nel senso che non è definito formalmente.
Un'interfaccia è la specifica di come una funzione, una classe o un oggetto interagisce con il resto del codice. Questo significato è ad esempio utilizzato nello standard C ++:
17.5.1.3/3: Interface convention requirements are stated as generally as possible. Instead of stating “class X has to define a member function operator++(),” the interface requires “for any object x of class X, ++x is defined.” That is, whether the operator is a member is unspecified.
Viene anche usato coerentemente da Bjarne Stroustrup in La progettazione e l'evoluzione di C ++ , Addison-Wessley, 1994, ad esempio quando spiega i principi fondamentali per le decisioni di progettazione linguistica che ha fatto per le classi:
(5) function definitions are typically specified elesewhere to make a class more like an interface specification than a lexical mechanism for organizing source code.
In altre parole, questo consente di avere una classe dichiarata in un'intestazione (l'interfaccia che può essere utilizzata attraverso tutte le unità di compilazione) e l'implementazione dei suoi membri definita in un'unità di compilazione, che inernl non deve essere conosciuto dal mondo esterno per utilizzare l'interfaccia.
Il termine "interfaccia" ha guadagnato popolarità con Java, dove è una caratteristica del linguaggio utilizzata per integrare l'ereditarietà singola. In C ++ puoi fare lo stesso usando un'eredità dalla cosiddetta classe di interfaccia astratta, come suggerito nello standard C ++:
10.4/1: An abstract class can also be used to define an interface for which derived classes provide a variety of implementations.
Per questo basta guardare l'ottimo esempio di risposta di Rado
Leggi altre domande sui tag interfaces c++ inheritance multiple-inheritance implementations