-
16.09.2017, 02:56 #1
Abstraktion von Klassen und Methoden
Hallo zusammen,
hier zunächst folgender Code-Ausschnitt:
public class RentalService {
private List<Car> cars = new ArrayList<>();
private List<Bike> bikes = new ArrayList<>();
private List<Client> clients = new ArrayList<>();
private Map<Client,List<Car>> carsPerClient = new HashMap<>();
private Map<Client,List<Bike>> bikesPerClient = new HashMap<>();
public int numberOfCars () {
return cars.size();
}
public int numberOfBikes () {
return bikes.size();
}
public boolean rentACar (Client client, Car car) {
if (client.age() < car.getMinAge()) {
System.out.println ("The minimum age to rent a car is "+car.getMinAge());
return false;
}
if (!clients.contains (client)) {
System.out.println ("Unknown client: "+client);
return false;
}
if (!cars.contains(car)) {
System.out.println ("Unknown car: "+car);
return false;
}
List<Car> carsOfClient = carsPerClient.get (client);
if (carsOfClient == null) {
carsOfClient = new ArrayList<>();
carsPerClient.put(client, carsOfClient);
}
carsOfClient.add (car);
return true;
}
public boolean rentABike (Client client, Bike bike) {
if (client.age() < bike.getMinAge()) {
System.out.println ("The minimum age to rent a biker is "+bike.getMinAge());
return false;
}
if (!clients.contains (client)) {
System.out.println ("Unknown client: "+client);
return false;
}
if (!bikes.contains(bike)) {
System.out.println ("Unknown bike: "+bike);
return false;
}
List<Bike> bikesOfClient = bikesPerClient.get (client);
if (bikesOfClient == null) {
bikesOfClient = new ArrayList<>();
bikesPerClient.put(client, bikesOfClient);
}
bikesOfClient.add (bike);
return true;
}
}
Schnell zu sehen ist, dass die Funktionen rentABike und rentACar redundanten Code besitzen. Um zu abstrahieren wurde für Bike und Car eine Oberklasse "Vehicles" geschaffen, die die in den Funktionen verwendeten Eigenschaften abbildet. Um nun auch eine abstrakte Funktion zu schreiben, habe ich folgenden Ansatz:
public boolean rentACar (Client client, Car car) {
return rentAVehicle(client, car, this.carsPerClient, this.cars); // this nur, damit es für euch leichter ist zu erkennen, dass ich die privaten Variablen meine
}
public boolean rentAVehicle(Client client, Vehicle vehicle, Map<Client,List<Vehicle>> vehiclesPerClient, List<Vehicle> vehicles) {
for (Client clientOfMap : vehiclesPerClient.keySet()) {
if (vehiclesPerClient.get(clientOfMap).contains(vehicle)) {
System.out.println("The vehicle " + vehicle + " is already rented by " + clientOfMap);
return false;
}
}
if (client.age() < vehicle.getMinAge()) {
System.out.println ("The minimum age to rent a vehicle is " + vehicle.getMinAge());
return false;
}
if (!clients.contains (client)) {
System.out.println ("Unknown client: "+client);
return false;
}
if (!vehicles.contains(vehicle)) {
System.out.println ("Unknown vehicle: "+ vehicle);
return false;
}
List<Vehicle> vehiclesOfClient = vehiclesPerClient.get(client);
if (vehiclesOfClient == null) {
vehiclesOfClient = new ArrayList<>();
vehiclesPerClient.put(client, vehiclesOfClient);
}
vehiclesOfClient.add(vehicle);
return true;
}
Problem ist allerdings, dass sich die List<Car> nicht zu List<Vehicle> logischerweise konvertieren lässt. Wie könnte man die o.g. Funktionen abstrahieren? Operatoren wie instanceof sollten vermieden werden, auch Typen wie z.B "? extends Vehicle".
Über Anregungen würde ich mich sehr freuen!Geändert von aquastar (16.09.2017 um 02:57 Uhr)
-
The Following 4 Users Say Thank You to aquastar For This Useful Post:
-
16.09.2017, 09:36 #2
AW: Abstraktion von Klassen und Methoden
Die einfachste Lösung wäre, wenn Vehicle ein Interface wäre, dessen Methoden von Car und Bike implementiert werden.
public interface Vehicle {
public enum TYPE {
CAR, BIKE;
}
public Type getType();
public int getMinAge();
}
public class Car implements Vehicle {
@Override
public Type getType() {
return TYPE.CAR;
}
@Override
public int getMinAge() {
return 18;
}
...
}
public class RentalService {
private List<Vehicle> vehicles = new ArrayList<>();
private List<Client> clients = new ArrayList<>();
private Map<Client, List<Vehicle>> vehiclesPerClient = new HashMap<>(); // Client muss hashCode() und equals(Object o) implementieren, um als Schlüssel für eine Map zu funktionieren
private int numberOfCars = 0;
private int numberOfBikes = 0;
public int getNumberOfCars() { return numberOfCars; }
public int getNumberOfBikes() { return numberOfBikes; }
public boolean rentAVehicle(Client client, Vehicle vehicle) {
if (client.getAge() < vehicle.getMinAge()) {
System.out.println("bla");
return false;
}
if (!clients.contains(client)) {
System.out.println("bla1");
return false;
}
if (!vehicles.contains(vehicle)) {
System.out.println("bla2");
return false;
}
List<Vehicle> vehiclesOfClient = vehiclesPerClient.get(client);
if (null == vehiclesOfClient) {
vehiclesOfClient = new ArrayList<>();
vehiclesPerClient.put(client, vehiclesOfClient);
}
vehiclesOfClient.add(vehicle);
switch (vehicle.getType()) {
case Vehicle.TYPE.CAR: ++numberOfCars; break;
case Vehicle.TYPE.BIKE: ++numberOfBikes; break;
}
return true;
}
}
Aber du schreibst:
Operatoren wie instanceof sollten vermieden werden, auch Typen wie z.B "? extends Vehicle"
Problem ist allerdings, dass sich die List<Car> nicht zu List<Vehicle> logischerweise konvertieren lässt.
https://dzone.com/articles/covarianc...contravariance
https://de.wikipedia.org/wiki/Kovari..._Kontravarianz
-
-
16.09.2017, 11:40 #3
AW: Abstraktion von Klassen und Methoden
An ein Enum habe ich auch schon gedacht, aber wäre dies nicht fast das Gleiche als würde man instanceof verwenden? Ich würde dies als Ansatz gar nicht schlecht finden, allerdings bin ich der Meinung, dass der Prof eine funktionale Änderung an den Klassen Car etc. nicht verwünscht. Die Aufgabenstellung fordert eine Vereinfachung der RentalService-Klasse. Ich bin mir unsicher, abzuwägen was nun als wirkliche Vereinfachung gelten würde. Denn auch bei deiner Lösung müsste man im Falle eines neuen FahrzTreugs (bspw. Truck) die rentATruck-Methode und numberOfTrucks-Parameter erstellen und die Funktion rentAVehicle erweitern (beim Zählen der Autos). Durch mein Beispiel hatte ich mir erhofft, dass man für ein neues Vehicle möglichst wenig erweitern muss. Allerdings erscheint das ein wenig schwierig ohne gewisse Mittel anwenden zu dürfen.
Interfaces dürfen leider auch nicht verwendet werden. Die Funktionen wie z.B: "rentACar" dürfen nicht gelöscht werden, da die vorherigen Signaturen zwingend bestehen bleiben müssen (Teil der Aufgabenstellung).
Die nicht mögliche Konvertierung habe ich als "logisch" angesehen, nachdem ich mich hiermit auseinandergesetzt habe: https://stackoverflow.com/questions/...s-implicitly-p
Logisch bleibt es dann wohl doch nicht. :-D
Dass der Client hashCode() implementieren muss war mir bisher nicht klar, wieso das denn?
-
16.09.2017, 12:17 #4
AW: Abstraktion von Klassen und Methoden
Keys einer Map müssen eindeutig identifizierbar, also unterscheidbar, sein. Das stellt die (korrekte) Implementierung von hashCode() und equals(Object o) sicher. Gängige IDEs können beide Methoden automatisch erzeugen.
Ja, bei deinem Stackoverflow Link werden, wie ich beim Überfliegen gesehen habe, die Themen, die ich auch angesprochen habe (Ko- und Kontravarianz), behandelt.
Kannst du vielleicht mal die ganze Aufgabenstellung + sämtlichen Sourcecode posten? Es lässt sich bestimmt eine Lösung finden.
-
Ähnliche Themen
-
[Methoden & Hilfe] Liebe, Selbstbewusstsein & co
Von WurstEsser im Forum ZwischenmenschlichesAntworten: 20Letzter Beitrag: 12.08.2014, 08:00 -
C# Klassen- und Instanzmethoden?
Von Gast78236 im Forum .NetAntworten: 4Letzter Beitrag: 18.01.2014, 02:30 -
Methoden Parameterrückgabe
Von aquastar im Forum JavaAntworten: 8Letzter Beitrag: 06.06.2012, 19:27 -
Methoden um Browser-Accounts zu lesen?
Von JumP-StyLe im Forum OffTopicAntworten: 5Letzter Beitrag: 03.06.2012, 19:50 -
[MW3] Eure Klassen
Von BMG im Forum Call of DutyAntworten: 4Letzter Beitrag: 29.05.2012, 16:56
Diese Seite nutzt Cookies, um das Nutzererlebnis zu verbessern. Klicken Sie hier, um das Cookie-Tracking zu deaktivieren.