24 votos

OOP problema de diseño

¿Qué es un buen diseño en este caso simple:

Digamos que tengo una base de Coches de clase con un método FillTank(Fuel fuel)donde el combustible es también una clase base que tienen varias clases de hoja, diesel, etanol, etc.

En mi hoja de coche de clase DieselCar.FillTank(Fuel fuel) sólo a un determinado tipo de combustible está permitido (no hubo sorpresas:)). Ahora, aquí está mi preocupación, de acuerdo a mi la interfaz de cada coche puede ser se derrumbó con cualquier combustible, pero me parece mal para mí, en cada FillTank() de ejecución revise la entrada de combustible para el tipo correcto y si no tirar error o algo.

¿Cómo puedo rediseño tal caso a una más precisa, es incluso posible? Cómo diseñar una base de método que toma una clase de base para la entrada sin llegar a estos "resultados extraños"?

28voto

El uso genérico de la clase base (si su idioma admite (la de abajo es de C#)):

public abstract class Car<TFuel>  where TFuel : Fuel
{
    public abstract void FillTank(TFuel fuel);
}

Básicamente, esto obliga a que cualquier clase que hereda de coche para especificar el tipo de combustible que utiliza. Además, el Car clase impone una restricción que TFuel debe ser algún subtipo de lo abstracto Fuel de la clase.

Digamos que tenemos alguna clase Diesel , el cual es simple:

public class Diesel : Fuel
{
    ...
}

Y un coche que sólo se ejecuta en diesel:

public DieselCar : Car<Diesel>
{
     public override void FillTank(Diesel fuel)
     {
          //perform diesel fuel logic here.
     }
}

12voto

Peter Alexander Puntos 31990

La programación orientada a objetos por sí solo no puede manejar este problema. Lo que usted necesita es genérico de programación (C++ solución se muestra aquí):

template <class FuelType>
class Car
{
public:
  void FillTank(FuelType fuel);
};

Su coche diesel es sólo un vehículo específico, Car<Diesel>.

11voto

Guest Puntos 11

Si hay un límite entre los tipos de los coches y los tipos de combustible, a continuación, FillTank() no tiene por qué estar en la base de la Car de clase, ya que el saber que usted tiene un coche no dirá qué tipo de combustible. Así, por este para garantizar la corrección en tiempo de compilación, FillTank() debe ser definido en las subclases, y sólo debe tomar la Fuel subclase que funciona.

Pero ¿y si tenemos un código común que usted no querrá repetir entre las subclases? A continuación, escribe un protegidas FillingTank() método de la clase base que la de la subclase, las llamadas a la función. Lo mismo va para Fuel.

Pero lo que si tiene un poco de magia coche que se ejecuta en múltiples combustibles, decir diesel o gasolina? Luego de que el coche se convierte en una subclase de DieselCar y GasCar y que necesita para asegurarse de que Car se declara como un virtual superclase, por lo que no tiene dos Car casos en un DualFuelCar objeto. Llenar el tanque Sólo debe Trabajar con poca o ninguna modificación: por defecto, obtendrá tanto DualFuelCar.FillTank(GasFuel) y DualFuelCar.FillTank(DieselFuel), dando como resultado una sobrecarga por tipo de función.

Pero lo que si usted no desea que la subclase tiene un FillTank() a la función? Entonces usted necesita para cambiar el tiempo de ejecución de la comprobación y de hacer lo que creía que tenía para: hacer que la subclase de verificación Fuel.type y echar una excepción o devolver un código de error (prefiero este último) si hay una discrepancia. En C++, RTTI y dynamic_cast<> son lo que yo recomendaría. En Python, isinstance().

1voto

stefaanv Puntos 7326

un doble envío puede ser utilizado para esto: aceptar algunas de combustible antes de llenarlo. La mente que en un lenguaje que no soportan directamente, introducir las dependencias

1voto

James Puntos 40024

Suena como que usted sólo desea restringir el tipo de combustible que va en su coche diesel. Algo así como:

public class Fuel
{
    public Fuel()
    {
    }
}

public class Diesel: Fuel
{
}

public class Car<T> where T: Fuel
{
    public Car()
    {
    }

    public void FillTank(T fuel)
    {
    }
}

public class DieselCar: Car<Diesel>
{
}

Iba a hacer el truco por ejemplo,

var car = new DieselCar();
car.FillTank(/* would expect Diesel fuel only */);

Básicamente lo que se está haciendo aquí es permitir que un Car tener específicos de los tipos de combustible. También permite que usted para crear un auto que admite cualquier tipo de Fuel (la probabilidad sería una cosa buena!). Sin embargo, en su caso, la DieselCar, sólo se puede derivar una clase de coche y lo limitan a usar Diesel de combustible solamente.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X