Zuerst eine Autoklasse:

public class Car {

    private final Engine engine;

    public Car(int x, int y) {

      this.engine = createEngine(x, y);

      // (...)
    }

    protected Engine createEngine(int x, int y) {
         return new Engine(x ,y);
    }
}

Jetzt möchte ich ein FastCar erstellen, das eine FastEngine benötigt, nicht nur eine Engine.

public class FastEngine extends Engine {

    public FastEngine(int x, int y, double a, double b) {
        super(x, y);
        // (...)
    }

    // (...)
}

public class FastCar extends Car {

    private final double a;
    private final double b;

    public FastCar(int x, int y, double a, double b) {
        super(x, y);
        this.a = a;
        this.b = b;
    }

    @Override
    protected Engine createEngine(int x, int y) {
        // of course I can't use a and b here, they were not initialized yet :( :( :(
        return new FastEngine(x, y /* I need a and b here too :( */);
    }
}

Das Problem ist also, dass ich in meiner neuen FastCar-Klasse die Engine gegen eine FastEngine austauschen muss, die FastEngine jedoch jetzt die im Konstruktor übergebenen Argumente a und b akzeptiert. Es sieht so aus, als wäre ich in eine Sackgasse geraten. Was kann ich tun, außer alles mit einem neuen Entitätsmodell von Grund auf neu zu schreiben?

-2
Josh 18 Jän. 2019 im 04:52

3 Antworten

Beste Antwort

Obwohl ich den Kommentaren zustimme, dass die Frage nicht gut formuliert ist, gebe ich Ihnen die Lösung. Fühlen Sie sich frei, Generika hinzuzufügen, um es schöner zu machen.

public class Car {

    static class CarConfig {
        int x;
        int y;

        CarConfig(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    private final Engine engine;

    public Car(int x, int y) {

      this(new CarConfig(x, y));
    }

    Car(CarConfig config) {
         this.engine = createEngine(config);
    }

    protected Engine createEngine(CarConfig config) {
         return new Engine(config.x ,config.y);
    }
}

Dann in Ihrer Unterklasse:

public class FastEngine extends Engine {

    public FastEngine(int x, int y, double a, double b) {
        super(x, y);
        // (...)
    }

    // (...)
}

public class FastCar extends Car {

    static class FastCarConfig extends CarConfig {
         double a;
         double b;

         FastCarConfig(int x, int y, double a, double b) {
             super(x, y);
             this.a = a;
             this.b = b;
         }
     }


    private final double a;
    private final double b;

    public FastCar(int x, int y, double a, double b) {
        super(new FastCarConfig(x, y, a, b);
        this.a = a;
        this.b = b;
    }

    @Override
    protected Engine createEngine(CarConfig config) {
        if (config instanceof FastCarConfig) throw new IllegalStateException("You messed up!");
        FastCarConfig c = (FastCarConfig) config;
        return new FastEngine(c.x, c.y, c.a, c.b);
    }
}

B O O M!

1
GBlodgett 18 Jän. 2019 im 05:16

Ich schlage vor, eine Motorenfabrik zu erstellen. Denken Sie an das Prinzip "Einzelverantwortung" (SOLID).

Im wirklichen Leben baut man den Motor nicht im Auto. Du machst es separat. Manchmal in einer anderen Fabrik. Der Motor wird am Fließband in das Auto eingebaut.

Dies gibt Ihnen mehr Flexibilität sowohl im Werk als auch im Code.

Ich schlage vor, ein Builder-Muster zu implementieren - wenn Sie mehr Teile in das Builder-Muster einbauen Wagen.

P.s. "statische" s ignorieren - Ich habe sie gerade hinzugefügt, um IDE-Warnungen zu vermeiden.

public static void main(String[] args) {
    Car car = new Car(EngineFactory.createEngine(1, 2));
    Car fastCar = new FastCar(EngineFactory.createEngine(1, 2, 1d, 2d), 1d, 2d);
}

static class EngineFactory{
    public static Engine createEngine(int x, int y){
        return new Engine(x, y);
    }

    public static Engine createEngine(int x, int y, double a, double b){
        return new FastEngine(x, y, a, b);
    }
}

public static class Car {
    private final Engine engine;
    public Car(Engine engine) {
        this.engine = engine;
    }
}

public static class FastCar extends Car {

    private final double a;
    private final double b;

    public FastCar(Engine engine, double a, double b) {
        super(engine);
        this.a = a;
        this.b = b;
    }
}

public static class FastEngine extends Engine {
    public FastEngine(int x, int y, double a, double b) {
        super(x, y);
    }
}

public static class Engine{
    int x;
    int y;

    public Engine(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
2
Azee 18 Jän. 2019 im 02:59

Bewegen Sie den Motor wieder in den Fahrzeugbauer. Wenn das Erstellen der Engines mehr als einen Konstruktoraufruf erfordert, verschieben Sie ihn in eine statische Konstruktorfunktion.

class Engine {
    private final int x;
    private final int y;

    Engine(int x, int y) {
      this.x = x;
      this.y = y;
    }
  }

  public class Car {
    private final Engine engine;

    public Car(int x, int y) {
      this(new Engine(x, y));
    }

    Car(Engine engine) {
      this.engine = engine;
    }
  }

  public class FastEngine extends Engine {
    private final double a;
    private final double b;

    FastEngine(int x, int y, double a, double b) {
      super(x, y);
      this.a = a;
      this.b = b;
    }
  }

  public class FastCar extends Car {
    public FastCar(int x, int y, double a, double b) {
      super(new FastEngine(x, y, a, b));
    }
  }
1
Mike 18 Jän. 2019 im 03:23