Domanda

Sto scrivendo un gioco semplicistico per imparare a fare un po 'più di esperienza in C ++, e ho un'idea di dove sento che il polimorfismo quasi funziona, ma non lo fa. In questo gioco, il Party si sposta in modo abbastanza lineare attraverso un Map, ma occasionalmente può incontrare un Fork sulla strada. Un fork è (sostanzialmente) un std::vector<location*>. Inizialmente stavo per scrivere qualcosa come il seguente nella funzione getNext() membro:

if(!CurrLocation->fork_.empty())
   // Loop through forks and show options to the player, go where s/he wants
else
  (CurrLocation++)

Ma mi chiedevo se qualche variante di quanto segue potesse essere migliore:

CurrLocation = CurrLocation->getNext();

Con Fork effettivamente derivato da Location e sovraccarico di alcune nuove funzioni location. Ma in quest'ultimo caso, UserInterface::* (una struttura di basso livello) dovrebbe essere quella per presentare il messaggio all'utente anziché & Quot; passando questo backup & Quot ;, che non la sensazione è elegante in quanto si accoppia da <=> a <=>.

Le tue opinioni?

È stato utile?

Soluzione

Tutti i problemi possono essere risolti aggiungendo un livello di riferimento indiretto. Vorrei usare la tua variante suggerita e disaccoppiare Location da Party consentendo a getNext di accettare un oggetto che risolva le scelte direzionali. Ecco un esempio (non testato):

class Location; 

class IDirectionChooser
{
public:
  virtual bool ShouldIGoThisWay(Location & way) = 0;
};

class Location
{
public:
  virtual Location * GetNext(IDirectionChooser & chooser)
  {
    return nextLocation;
  }

  virtual Describe();
private:
  Location * nextLocation;
};

class Fork : public Location
{
public:
  virtual Location * GetNext(IDirectionChooser & chooser)
  {
    for (int i = 0; i < locations.size(); i++)
      if (chooser.ShouldIGoThisWay(*locations[i]))
        return locations[i];
  }
  virtual Describe();
private:
  vector<Location *> locations;
};

class Party : public IDirectionChooser
{
public:
  void Move()
  {
    currentLocation = currentLocation->GetNext(GetDirectionChooser());
  }

  virtual IDirectionChooser & GetDirectionChooser() { return *this; }

  virtual bool ShouldIGoThisWay(Location & way)
  {
    way.Describe();
    cout << "Do you want to go that way? y/n" << endl;

    char ans;
    cin >> ans;
    return ans == 'y';
  }
};

Altri suggerimenti

Dovresti usare il polimorfismo purché abbia senso e semplifichi il tuo design. Non dovresti usarlo solo perché esiste e ha un nome di fantasia. Se semplifica la progettazione, vale la pena accoppiare.

La correttezza e la semplicità dovrebbero essere l'obiettivo finale di ogni decisione progettuale.

Penso che tu abbia individuato i problemi da solo e che probabilmente tu possa risolverli con la tua conoscenza del resto del sistema o qualche altro dettaglio qui che possiamo esaminare.

Come è stato menzionato:

  1. Il polimorfismo dovrebbe essere usato per semplificare il design, cosa che farebbe in questo caso, così ben individuato.
  2. Si riscontra un problema con l'accoppiamento: di nuovo ben individuato, l'accoppiamento può causare problemi in seguito. Tuttavia, ciò che mi dice è il modo in cui sei applicare il polimorfismo potrebbe non essere il modo migliore.
  3. La programmazione alle interfacce dovrebbe consentire di nascondere i dettagli interni di come il sistema è stato messo insieme e ridurre così l'accoppiamento.

Il polimorfismo non si presta a un maggiore accoppiamento, penso che siano questioni separate.

In effetti, se si sta programmando interfacce e seguendo l'inversione generale dei modelli di controllo, si otterrà un accoppiamento minore o nullo.

Nel tuo esempio, non vedo come la posizione è accoppiata a UserInterface?

In questo caso, è possibile rimuovere l'accoppiamento attraverso un altro livello di astrazione tra UserInterface e Location, come LocationViewAdapter?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top