2012-08-06 11 views
7

Considera di avere qualche astrattoVehicle classe e classi astratte di auto, camion, moto che derivano da Vehicle. Immaginate anche che io debba essere in grado di creare un'auto a base di carburante o elettrica, e così via per camion e moto. (classi concrete)Come creare un metodo polimorfico con diverse firme

due domande:

1.Consider che voglio riempire di energia in un veicolo senza sapere quello che è, in un certo senso polimorfico. Per esempio se il veicolo è di carburante basa voglio riempirlo di carburante e il metodo dovrebbe essere con 3 parametri:
void FillUpEnergy(EfuelType i_fuelType,int amounOfEnergy, int maxAmountOfEnergy)

ma per il veicolo electricy basato Ho bisogno quasi la stessa funzione signture ma questa volta senza tipo di carburante di naturalmente, per esempio (2 parametri):

void FillUpEnergy(int amounOfEnergy, int maxAmountOfEnergy) 

Posso fare un FillUpEnergy metodo polymorhic con i vincoli di cui sopra? (firme di metodo diverso)

2.In mia implementazione di tutte le classi di cemento in possesso di un riferimento per Engine (un altro classe astratta), che rappresentano un FuelEngine o ElectricEngine (altre classi concrete che ho che derivano dal motore). Ad esempio, ho una classe di calcestruzzo denominata ElectricCar che contiene un riferimento per ElectricEngine.
Questa architettura è abbastanza buona o ci sono modi migliori per implementare un sistema di garage? (In termini di oggetto di design orientato ecc ..)

+1

non riesce quasi mai 1) Per quanto riguarda la 2), si chiama Ponte ed è uno dei modelli di progettazione. –

+0

Anche il pattern di bridge è stato il mio primo pensiero. –

risposta

8

Non è possibile effettuare un metodo polimorfico "push-style" con firme diverse, ma si può fare un metodo polimorfico "pull-style" con il ben pubblicizzata Visitor Pattern.

L'idea è quella di invertire la sequenza di interazione, e lasciare che l'oggetto automobile decidere cosa fare: Invece di chiamare FillUpEnergy e dando l'auto ciò che si pensa di cui ha bisogno, chiamare FillUpEnergy e lasciare che la macchina prendere cosa sa ha bisogno, in questo modo:

interface IEnergyProvider { 
    void TakeFuel(EfuelType i_fuelType, int amounOfEnergy); 
    void TakeElectricity(int amounOfEnergy); 
} 
interface ICar { 
    void FillUpEnergy(IEnergyProvider provider); 
} 

Ora la firma del metodo polimorfico è fisso, ma l'invio del metodo prende due gambe invece di uno:

  • ti chiamano myCar.FillUpEnergy(myProvider)
  • La vettura chiama myProvider.TakeFuel o myProvider.TakeElectricity
+2

bella risposta! Manca il vecchio avatar però – dash

+1

ma non è qui visitatore complesso inutile? Considerando che prendere l'elettricità e prendere qualsiasi altro tipo di carburante suona come lo stesso concetto ... –

+0

@Sebastian Hai perfettamente ragione sul modello di visitatore: può facilmente sfuggire di mano, soprattutto se è necessario mantenere l'estensibilità. Ma nei casi di gerarchie che potrebbero essere specificate in anticipo, come questa, non dovrebbe essere un grosso problema: con solo una manciata di metodi, camminare attraverso le interazioni nella tua mente rimane facile. Per quanto riguarda il gas e l'elettrico sono lo stesso concetto, penso che il design rifletta quello fornendo un singolo metodo "FillUpEnergy". – dasblinkenlight

3

Riguardo la domanda 1)

Si potrebbe fare parte elettrica/benzina della fueltype e gestire questo nella vostra logica di dominio.

C# non offre il polimorfismo con diverse firme.

2) è chiamato Composizione

0
  1. Non puoi farlo, perché sarebbe esattamente una violazione di incapsulamento.
  2. Non capisco la tua domanda sui motori, ma posso sicuramente dire che ci potrebbero essere molti modi migliori per implementare il "sistema di garage" solo perché ci sono così tanti diversi "sistemi di garage". Il che significa che non dovresti provare a modellare il tuo sistema (in termini di OOP o altri termini) fino a quando non avrai compreso bene le tue esigenze.
1

Cosa distingue lo ElectricCar dallo FueledCar? Nient'altro che il motore (concettualmente):

interface IEngine 
{ 
    void FillUpFuel(int amountOfFuel, int maxAmountOfFuel); 
} 

class ElectricEngine : IEngine 
{ 
    public void FillUpFuel(int amountOfFuel, int maxAmountOfFuel) { ... } 
} 

abstract class Vehicle 
{ 
    public abstract IEngine Engine { get; } 
} 

class Car : Vehicle 
{ 
    public IEngine _engine; 
    public override IEngine Engine { get { return _engine; } } 

    public Car(IEngine engine) 
    { 
     _engine = engine; 
    } 
} 
... 
var electricCar = new Car(new ElectricEngine()); 
electricCar.Engine.FillUpFuel(40, 70); 

Esempio di composizione tipica rispetto ad ereditarietà. Il nome è un po 'strano con ElectricEngine che riempie il carburante ... ma non è questo il punto.

0

Circa 1)
Il punto di avere FillUpEnergy polimorfico (subtype polymorphism) è quello di essere in grado di chiamare questo metodo quando l'unica cosa che si sa è che l'oggetto è un Vehicle.

Se è necessario conoscere il tipo esatto per scegliere l'insieme corretto di argomenti, non è necessario che questa funzione sia polimorfica.

Circa 2)
Niente di sconvolgente

Problemi correlati