2012-08-06 11 views
7

Considere que tengo algunos abstractosVehicle clases abstractas de clase y auto, camión, motocicleta que derivan de Vehicle. También imagine que tengo que poder crear un automóvil con base de combustible o un automóvil con base eléctrica, y así también para camiones y motocicletas. (clases concretas)¿Cómo puedo hacer un método polimórfico con diferentes firmas?

dos preguntas:

1.Consider que quiero llenar de energía en un vehículo sin saber lo que es, de una forma polimórfica. Por ejemplo, si el vehículo se basa combustible quiero llenarlo de combustible y el método debería ser con 3 parámetros:
void FillUpEnergy(EfuelType i_fuelType,int amounOfEnergy, int maxAmountOfEnergy)

pero para vehículo basado electricy que necesito casi el mismo signture función, pero esta vez sin el tipo de combustible de curso, por ejemplo (2) parámetros:

void FillUpEnergy(int amounOfEnergy, int maxAmountOfEnergy) 

¿Puedo hacer una FillUpEnergy método Polymorhic con las limitaciones anteriores? (firmas diferentes de método)

2.In mi aplicación todas las clases concretas tienen una referencia para Engine (otra clase abstracta) que representan un FuelEngine o ElectricEngine (otras clases concretas que tengo que derivan de motor). Por ejemplo, tengo una clase concreta llamada ElectricCar que contiene una referencia para ElectricEngine.
¿Es esta arquitectura lo suficientemente buena o hay mejores formas de implementar un sistema de garaje? (En términos de diseño orientado a objetos, etc ..)

+1

yo no lo entiendo muy 1) En cuanto a 2), se llama puente y es uno de los patrones de diseño. –

+0

El patrón del puente fue mi primer pensamiento también. –

Respuesta

8

No se puede hacer un método polimórfico "push-estilo" con diferentes firmas, pero se puede hacer un método polimórfico "estilo tirón" con el Visitor Pattern bien publicitado.

La idea es invertir la secuencia de la interacción, y dejar que el objeto coche decidir qué hacer: En lugar de llamar FillUpEnergy y dando el coche lo que usted piensa que necesita, llame FillUpEnergy y dejar el coche tomar lo se sabe que necesita, así:

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

Ahora la firma de su método polimórfico es fijo, pero el envío del método toma dos piernas en lugar de uno:

  • se llama a myCar.FillUpEnergy(myProvider)
  • El coche llama myProvider.TakeFuel o myProvider.TakeElectricity
+2

¡buena respuesta! Se pierda el viejo avatar aunque – dash

+1

pero no es visitante complejo innecesario aquí? En cuanto a que tomar electricidad y tomar cualquier otro tipo de combustible suena como el mismo concepto ... –

+0

@Sebastian Tiene toda la razón sobre el patrón de visitante: puede salirse de control fácilmente, especialmente si necesita mantener la extensibilidad. Pero en casos de jerarquías que podrían especificarse por adelantado, como esta, no debería ser un gran problema: con solo un puñado de métodos, es fácil recorrer las interacciones en su mente. En cuanto a alimentar con gas y electricidad con el mismo concepto, creo que el diseño refleja eso al proporcionar un único método de 'FillUpEnergy'. – dasblinkenlight

3

Sobre la pregunta 1)

Se podría hacer parte/gasolina eléctrica de la fueltype y manejar esto en su lógica de dominio.

C# no ofrece polimorfismo con diferentes firmas.

2) se denomina Composición

0
  1. No se puede hacer eso, porque sería exactamente una violación de encapsulación.
  2. No entiendo su pregunta con respecto a los motores, pero seguramente puedo decir que podría haber muchas formas mejores de implementar el "sistema de garaje" simplemente porque hay tantos "sistemas de garaje" diferentes. Lo que de hecho significa que no debe intentar modelar su sistema (en términos de OOP o cualquier otro término) hasta que obtenga una buena comprensión de sus requisitos.
1

¿Qué distingue a ElectricCar del FueledCar? Nada más que el motor (conceptualmente):

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); 

Ejemplo típico de composición vs herencia. Naming es un poco extraño con Electric Engine llenando combustible ... pero ese no es el punto.

0

Sobre 1)
El punto de tener FillUpEnergy polimórfico (subtype polymorphism) es ser capaz de llamar a este método cuando lo único que se sabe es que el objeto es un Vehicle.

Si necesita saber el tipo exacto para elegir el conjunto correcto de argumentos, entonces no es necesario que esta función sea polimórfica.

Sobre 2)
Nada impactante

Cuestiones relacionadas