Che cos'è esattamente la conformità all'interfaccia in C ++?

0

Stavo leggendo questo . Dice che

Some people believe that the purpose of inheritance is code reuse. In C++, this is wrong. Stated plainly, “inheritance is not for code reuse.

The purpose of inheritance in C++ is to express interface compliance (subtyping), not to get code reuse. In C++, code reuse usually comes via composition rather than via inheritance. In other words, inheritance is mainly a specification technique rather than an implementation technique.

Quindi, la mia domanda è che cosa esattamente interfaccia la conformità (sottotipizzazione) in C ++? Come viene usata l'eredità per esprimerla? Come subtyping & le sottoclassi sono diverse? Sarebbe meglio se qualcuno rispondesse dando un esempio del mondo reale adatto.

    
posta Destructor 29.08.2015 - 20:25
fonte

2 risposte

1

Piuttosto che avere un codice riusabile, hai un codice che è intercambiabile.

Un esempio di vita reale che utilizza i picchietti DI e Adapter. Supponiamo che tu abbia una classe, che gestisce i dati. Non recupera i dati, ma li gestisce. Potremmo chiamarlo semplicemente DataHandler.

class DataHandler
{
public:
    void doSomethingWithData() {}
protected:
private:
};

Quando inizi a utilizzare DataHandler nella tua app, lo usi per gestire i dati da un database SQL. Quindi DataHandler avrà bisogno di un'istanza di detta classe.

class SqlDatabaseDataRetriever
{
public:
    Data getData() { }
protected:
private:
};

class DataHandler
{
public:
    DataHandler(SqlDatabaseDataRetriever& dataRetriever)
    {
        _dataRetriever = dataRetriever;
    }

    void doSomethingWithData()
    {
        Data data = this->_dataRetriever.getData();
    }
protected:
    SqlDatabaseDataRetriever _dataRetriever;
private:
};

Ma se successivamente decidessi, non vuoi accedere al database direttamente tramite SqlDatabaseDataRetriever , quindi crei un'API e crei una nuova classe che viene utilizzata per gestire la richiesta tramite la tua API e recupera i dati da essa .

Quindi vogliamo utilizzare la classe DataHandler con il nostro nuovo ApiDataRetriever , ma attualmente il nostro DataHandler utilizza una classe diversa. Potresti semplicemente riscrivere il tuo codice, iniettare invece ApiDataRetriever , ma c'è una soluzione migliore.

Creerai una classe astratta, che erediterà tutti i tuoi DataRetriever, inserirai questa classe astratta e utilizzerai i suoi metodi.

class DataRetriever
{
public:
    virtual Data getData() = 0;
protected:
private;
}

class SqlDatabaseDataRetriever : public DataRetriever
{
public:
    virtual Data getData() { }
protected:
private;
}

class ApiDataRetriever : public DataRetriever
{
public:
    virtual Data getData() { }
protected:
private;
}

class DataHandler
{
public:
    DataHandler(DataRetriever& dataRetriever)
    {
        _dataRetriever = dataRetriever;
    }

    void doSomethingWithData()
    {
        Data data = this->_dataRetriever.getData();
    }
protected:
    DataRetriever _dataRetriever;
private:
};

Poiché la funzione nella classe genitore è definita come pura virtuale, deve essere implementata in classe figlio e poiché si sta iniettando la classe genitore, ma questa non può essere istanziata, si otterrà sempre una classe soggetto che ha il metodo genitore , che puoi usare senza vincoli.

    
risposta data 29.08.2015 - 20:55
fonte
1

Un sottotipo è un tipo che soddisfa il contratto di un tipo di base.

Una sottoclasse è una classe che eredita da una classe di riferimento.

In C ++ (trascurando i modelli) è possibile creare un sottotipo solo per sottoclasse, che fornisce al compilatore molte informazioni aggiuntive utili per l'ottimizzazione e il controllo statico.
Lo stesso non si può dire dell'obiettivo-c, in cui un sottotipo deve solo gestire i messaggi che il basetype comprende allo stesso modo: Duck-typing "Se sembra un'anatra, nuota come un'anatra e caga come un'anatra, allora probabilmente è un'anatra."
Anche i template C ++ sono tipografici (i tipi devono avere membri appropriati), anche se completamente in fase di compilazione e quindi non incorrere in nessuna delle penalizzazioni della digitazione dinamica.

Un esempio di sottotipizzazione senza sottoclasse sarebbe utilizzando algoritmi standard:

template<class T> void sortall(T& x) {
    using std::begin;
    using std::end;
    std::sort(begin(v), end(v));
}

Che può essere chiamato se l'argomento è un std::vector , un std::array o qualche altro contenitore, anche se nessuno degli esempi è correlato per ereditarietà.

Sebbene la sottoclassificazione senza subdovisione sia possibile ignorando il contratto ereditato, è un peccato che dovrebbe semplicemente astenersi dal commettere.

    
risposta data 29.08.2015 - 22:20
fonte

Leggi altre domande sui tag