Java Anfängerfragen Java-Einstieg

Der Konstruktor:
Die Klasse Auto und die Klasse Moped bekommt einen
In der wird wird die Anzahl Räder und die Durchschnittsgeschwindigkeit definiert

Bekommt die Klasse Fahrzeug auch einen Konstruktor wenn Auto und Moped einen bekommen? (bzw. sollte Fahrzeug einen bekommen wenn auto und...)

Anzahl Räder und Durchschnittsgeschwindigkeit sind ja Eigenschaften, die alle Fahrzeuge haben, deswegen ist es am besten, dafür einen Konstruktor in der Klasse Fahrzeug zu bauen:

PHP:
abstract class Fahrzeug {
    protected int anzahlRaeder;
    protected int durchschnittsGeschwindigkeit;
    public Fahrzeug(int raeder, int geschw) {
        this.anzahlRaeder = raeder;
        this.durchschnittsGeschwindigkeit = geschw;
    }
}

class Motorrad extends Fahrzeug {
    public Motorrad(int geschw) {
        super(2, geschw);
    }
}

Und noch ne kleine Steigerung:
Implements:
Soweit ich das verstanden habe implementiert (also zwingt) Fahrzeug seine Unterklassen dazu eine Bestimmte Methode bereitzustellen, nur wie schreibe ich das ?
[/quote]

Das stimmt so halb. Der wesentliche Unterschied ist, dass "implements" mit Interfaces benutzt wird, nicht mit Klassen. Ein Interface enthält nur Methodendeklarationen ohne Implementation. Das könnte in diesem Fall so aussehen:

PHP:
interface Fahrzeug {
    void losfahren();
    void anhalten();
}

class Motorrad implements Fahrzeug {
    public void losfahren() {
        // tu was
    }

    public void anhalten() {
        // tu was
    }
}
[/code]

Wenn du nicht beide Methoden in Motorrad implementierst, bekommst du einen Compilerfehler. den gleichen Effekt könntest du auch erzielen, wenn du Fahrzeug als abstrakte Klasse und anhalten() und losfahren() darin als abstrakte Methoden deklarierst.
 
Ich würde ja nur zu gerne wissen was abstact, Interface und Instanz bedeutet nur denke ich dass ich das selber irgendwo nachschlagen sollte anstatt es von einem von euch zu hören, nur habe ich heute mehr gelernt als in den 6 Monaten an der Oberschule. :lol: (traurig, aber wahr)


edit:
Was mich an deinem (oberen) Code am meisten verwirrt ist die tatscahe, dass überalle variablen und keine festen zahlen verwendet wurden (bis auf 2)
Wocher sollen diese denn kommen und wie soll man diese einbinden?
Mit Scanner? nein.
PHP:
public Fahrzeug(int raeder, int geschw) {
this.anzahlRaeder = raeder;
this.durchschnittsGeschwindigkeit = geschw;
}
Ist der Konstruktor von Fahrzeug und gibt jedem abgeleiteten Object die Werte anzahlRaeder und dursch...keit mit.

Und
PHP:
public Moped int geschw) {
super(2, geschw);
}

bzw.
PHP:
public Auto int geschw) {
super(4, geschw);
}

sind die jeweiligen Konstruktoren der Klassen Moped und Auto.

Die Funktion (darf ich Funktion sagen? :D)) ruft den Konstruktor der Hauptklasse (Also Fahrzeug) auf und gibt ihm die beiden Parameter (2/4 und geschw) mit.
 
Zuletzt bearbeitet:
It'sNever2Late! schrieb:
Ein neues Beispiel

Klasse Fahrzeug
Anzahl Räder
Geschwindigkeit

Kasse Moped extends Fahrzeug
Höchstgeschwindigkeit (z.B.)

Klasse Auto extends Fahrzeug
Fenter
Radio
Kofferraum
...

Klasse Fahrzeug hat ne Methode "losfahren" und "anhalten"

Klasse Auto hat ne Methode "Türen öffnen" und "Radio einschalten"

Klasse Moded hat ne Methode "Auf einem Rad fahren" und "360°-Drehung machen"

Auto kann keine Methoden von Moped aufrufen und andersrum genausowenig.

Yep, so ist das gedacht.


It'sNever2Late! schrieb:
Ich meine ich habe das jetzt verstanden. Also steigern wir das ganze mal etwas:

Der Konstruktor:
Die Klasse Auto und die Klasse Moped bekommt einen
In der wird wird die Anzahl Räder und die Durchschnittsgeschwindigkeit definiert

Bekommt die Klasse Fahrzeug auch einen Konstruktor wenn Auto und Moped einen bekommen? (bzw. sollte Fahrzeug einen bekommen wenn auto und...)

Das kommt darauf an. Wenn Fahrzeug bereits Felder zur Verfügung stellt, dann ist es üblich, dass Fahrzeug auch entsprechende Konstruktoren zur Verfügung stellt, wo sinnvoll (die dann ev. nur protected sind damit sie nur von abgeleiteten Klassen verwendet werden können).

Man kann die Felder auch protected deklarieren, dann kann man in den Konstruktoren von Moped und Auto auch direkt darauf zugreifen bzw. diese zuweisen.

Wenn möglich sollte man Felder final deklarieren, dann meckert der Compiler, wenn ein Feld im Konstruktor nicht zugewiesen wird.

Man kann aber die Eigenschaften (Felder) auch mittels Methoden setzen. Konstruktoren sind nicht zwingend.
 
Noch mal zu der Person/Beamter-Geschichte: Die Zuweisung

PHP:
Person person = new Beamter();

legt ein Objekt der Klasse Beamter an und erzeugt darauf eine Referenz namens person. Diese Referenz ist allerdings eine Person-Referenz, keine Beamter-Referenz. Das bedeutet, dass über diese Referenz nur Zugriffe auf diejenigen Eigenschaften des Objekts möglich sind, die aus der Person-Klasse kommen.

(Dafür könnte man dieser Referenz später auch eine Instanz einer anderen Person-Klasse zuweisen, z. B. - angenommen, Rentner sei eine Unterklasse von Person:
PHP:
person = new Rentner();
Wenn person eine Beamter-Referenz wäre, ginge das nicht.

Aber wie gesagt: Das zugrundeliegende Objekt ist nach wie vor ein Beamter-Objekt, weshalb du seine Beamter-spezifischen Eigenschaften sehr wohl benutzen kannst. Du brauchst dafür nur eine Beamter-Referenz, die du am einfachsten so bekommst:

PHP:
Beamter beamter = (Beamter)person;

Das Objekt bleibt dabei ein und dasselbe - Du bekommst nur eine zweite Zugriffsmöglichkeit darauf.
 
@ Konstruktor
Lest meinen Edit @ #22
Wenn möglich sollte man Felder final deklarieren, dann meckert der Compiler, wenn ein Feld im Konstruktor nicht zugewiesen wird.
Anstatt final nutze ich dann leiber protected. (kenne die Unterschiede, final => unveränderbar, protected => nicht von außen(wo soll das sein?(etwa ne abgeleitete Klasse(die kann das doch sowieso nicht?))) ansprechbar)

Man kann aber die Eigenschaften (Felder) auch mittels Methoden setzen. Konstruktoren sind nicht zwingend.
Mir erscheint das mit dem konstruktor sinnvoller als mit ner Methode, da diese erst aufgerufen werden muss (obwohl man dann mit Parametern(ihr nennt die Teile Argumente:D)) rumspielen kann, etc)


@ Zuweisung/Referenz

Ich fasse das zusammen was ich verstanden habe:

PHP:
Person mutter = new Person();
kann nur die Methoden der Klasse Person aufrufen.

PHP:
Beamter vater = new Beamter();
kann nur die Methoden der (wenn auch abgeleiteten) Klasse Beamter aufrufen.

PHP:
Person sohn = new Beamter();
Kann die Methoden der Klasse Person aufrufen, und dann kann man aus dem Beamten noch nen Renter machen und ändern somit seine Referenz, aber ich habe noch niht verstanden was das bringen soll, da er weiterhin nur die Methoden der Klasse Person aufrufen kann.
 
Zuletzt bearbeitet:
Was mich an deinem (oberen) Code am meisten verwirrt ist die tatscahe, dass überalle variablen und keine festen zahlen verwendet wurden (bis auf 2)
Wocher sollen diese denn kommen und wie soll man diese einbinden?.

Die Werte übergibst du beim Aufruf von new(). Schreibst du etwa
PHP:
Motorrad mrad = new Motorrad(60);
wird der Motorrad-Konstruktor mit dem Wert 60 für "geschw" aufgerufen.

It'sNever2Late! schrieb:
Ich würde ja nur zu gerne wissen was abstact, Interface und Instanz bedeutet nur denke ich dass ich das selber irgendwo nachschlagen sollte anstatt es von einem von euch zu hören, nur habe ich heute mehr gelernt als in den 6 Monaten an der Oberschule. :lol: (traurig, aber wahr)

Eine Instanz einer Klasse ist nur ein Objekt dieser Klasse. Zum Beispiel ist mrad in meinem Beispiel oben eine Instanz der Klasse Motorrad.

Abstrakte Klassen sind Klassen, von denen du keine Instanzen erzeugen darfst. Typischerweise handelt es sich dabei um Konzepte wie "Fahrzeug". Wenn du jeden möglichen Fahrzeugtyp (Auto, Motorrad usw.) durch eine eigene Unterklasse darstellst, dann ist es sinnlos, "Fahrzeug fahrzeug = new Fahrzeug()" zu schreiben, sondern man sollte immer die konkrete Klasse benutzen.

Das gilt besonders, wenn die abstrakte Klasse abstrakte Methoden enthält. Eine abstrakte Methode ist nicht implementiert - es gibt keinen Code dazu. (Diese Methoden sind daher nur in abstrakten Klassen erlaubt, nicht in konkreten.) Wenn du in der Klasse Fahrzeug zum Beispiel eine abstrakte Methode "losfahren()" deklarierst, dann heißt das, das alle konkreten Fahrzeuge - also alle (nicht-abstrakten) Unterklassen von Fahrzeug - eine solche Methode implementieren müssen. Der Sinn dabei ist, dass, selbst wenn du nur eine Fahrzeug-Referenz hast (siehe mein Post weiter oben :)), du darauf losfahren() aufrufen kannst - obwohl der Code, der das Losfahren tatsächlich bewerkstelligt, nicht in der Fahrzeug-Klasse liegt, sondern in (z. B.) Motorrad. Du musst nicht wissen, dass das Objekt "hinter" der Referenz ein Motorrad ist. Die Aussage der abstrakten Methodendeklaration ist also quasi "Alle Fahrzeuge können losfahren. Wie, ist mir egal."

Ein Interface kannst du dir vereinfacht vorstellen als eine abstrakte Klasse, die nur abstrakte Methoden und sonst nichts enthält. Zusätzlich ist der Unterschied, dass Interfaces nicht mit "extends", sondern mit "implements" eingebunden werden, und dass eine Klasse mehrere Interfaces einbinden kann.
Ergänzung ()

It'sNever2Late! schrieb:
Anstatt final nutze ich dann leiber protected. (kenne die Unterschiede, final => unveränderbar, protected => nicht von außen(wo soll das sein?(etwa ne abgeleitete Klasse(die kann das doch sowieso nicht?))) ansprechbar)

protected bedeutet: kann nur von Methoden der eigenen Klasse und von abgeleiteten Klassen betrachtet und verändert werden.

Mir erscheint das mit dem konstruktor sinnvoller als mit ner Methode, da diese erst aufgerufen werden muss (obwohl man dann mit Parametern(ihr nennt die Teile Argumente:D)) rumspielen kann, etc)

Ein gutes Prinzip ist: Alle Werte, die nötig sind, damit das Objekt funktioniert, im Konstruktor zu übergeben. Dann ist garantiert, dass das konstruierte Objekt funktioniert, ohne dass noch zusätzliche Methodenaufrufe nötig sind, was schöner ist.

Und ja, Argument oder Parameter ist eigentlich gehupft wie gesprungen :D

@ Zuweisung/Referenz

Ich fasse das zusammen was ich verstanden habe:

PHP:
Person mutter = new Person();
kann nur die Methoden der Klasse Person aufrufen.

PHP:
Beamter vater = new Beamter();
kann nur die Methoden der (wenn auch abgeleiteten) Klasse Beamter aufrufen.

Das "nur" ist hier irreführend. Da Beamter eine Unterklasse von Person ist, enthält die Klasse Beamter auch alle Methoden von Person (außer denen, die private sind, aber das ist in diesem Fall egal). Das heißt, "vater" kann auch alle Methoden aus Person aufrufen.

PHP:
Person sohn = new Beamter();
Kann die Methoden der Klasse Person aufrufen, und dann kann man aus dem Beamten noch nen Renter machen und ändern somit seine Referenz, aber ich habe noch niht verstanden was das bringen soll, da er weiterhin nur die Methoden der Klasse Person aufrufen kann.
[/quote]

Vorsicht jetzt :) Ja, der Sohn kann die Methoden aus Person aufrufen, aber du kannst keinen Rentner (aus dem Objekt) machen. Was du machen kannst, ist
PHP:
sohn = new Rentner();
Dabei biegst du allerdings die Referenz um, das heißt, die Referenz "sohn" verweist jetzt auf ein anderes Objekt von einem anderen Typ.* Das geht hier deshalb, weil das alte und neue Objekt beide Instanzen von Klassen sind, die Unterklassen von Person (dem Referenz-Typ) sind. Wäre die Referenz sohn eine Beamter-Referenz, dann ginge das nicht.

* Das Objekt, auf das die Referenz vorher gezeigt hat (der Beamte), hat danach mit der sohn-Referenz nichts mehr zu tun. Wenn es noch andere Referenzen auf ihn gibt, dann kannst du durch diese weiterhin auf ihn zugreifen. Wenn "sohn" die einzige Referenz auf ihn war, dann ist das Objekt danach nicht mehr verfügbar und wird von der Java-Maschine aufgeräumt.
 
Eine Instanz einer Klasse ist nur ein Objekt dieser Klasse. Zum Beispiel ist mrad in meinem Beispiel oben eine Instanz der Klasse Motorrad.
Verstanden.
Das was ich Object vom Typ Moped nenne ist einfach ne Instanz, supi.

Abstrakte Klassen sind Klassen, von denen du keine Instanzen erzeugen darfst. Typischerweise handelt es sich dabei um Konzepte wie "Fahrzeug". Wenn du jeden möglichen Fahrzeugtyp (Auto, Motorrad usw.) durch eine eigene Unterklasse darstellst, dann ist es sinnlos, "Fahrzeug fahrzeug = new Fahrzeug()" zu schreiben, sondern man sollte immer die konkrete Klasse benutzen.
Verstanden.
Macht ja auch keinen Sinn ne Instanz :p von Fahrzeug zu erstellen.

Das gilt besonders, wenn die abstrakte Klasse abstrakte Methoden enthält. Eine abstrakte Methode ist nicht implementiert - es gibt keinen Code dazu. (Diese Methoden sind daher nur in abstrakten Klassen erlaubt, nicht in konkreten.)
Konkrete Klassen sind?
Entweder "Fahrzeug" ohne abstract oder aber "Moped extends Fahrzeug", "Auto extends Fahrzeug", etc?
Gehen wir mal davon aus, dass konkrete Klassen einfach nicht-abstrakte Klassen sind. (ich weiß google......)

abstrakte Methoden (also Methoden innerhalb ner Abstakten Klasse (in diesem Fall dein Beispiel abstract Fahrzeug))) sind nicht implementiert. Also nicht zwingend? wenn diese nicht getippt werden gibt es auch keinen Code dazu? :D Oder meinst du leere Methoden?

Wenn du in der Klasse Fahrzeug zum Beispiel eine abstrakte Methode "losfahren()" deklarierst, dann heißt das, das alle konkreten Fahrzeuge - also alle (nicht-abstrakten) Unterklassen von Fahrzeug - eine solche Methode implementieren müssen.
Beispiel(so wie ich es verstanden habe:)
PHP:
abstract class Fahrzeug{
  abstract public/*erlaubt?*/ String kaufen(){
    System.out.print("Du hast dir soeben ein Fahrzeug gekauft. gz");
  }
}

PHP:
class Moped extends Fahrzeug{
  abstract public String kaufen(){
    System.out.print("Du hast dir soeben ein Moped gekauft. gz");
  }
  // Jetzt habe ich die zweimal, was unsinn ist
  // außer ich überschreibe (override) sie
  
}

PHP:
class Auto extends Fahrzeug{
  abstract public String kaufen(){
    System.out.print("Du hast dir soeben ein Auto gekauft. gz");
  }
  
}

Der Sinn dabei ist, dass, selbst wenn du nur eine Fahrzeug-Referenz hast (siehe mein Post weiter oben ), du darauf losfahren() aufrufen kannst - obwohl der Code, der das Losfahren tatsächlich bewerkstelligt, nicht in der Fahrzeug-Klasse liegt, sondern in (z. B.) Motorrad.
Das bedeutet, dass die Methode losfahren(); in der Klasse Motorrad implements Fahrzeug vorhanden sein muss, aber nicht in Fahrzeug?

Du musst nicht wissen, dass das Objekt "hinter" der Referenz ein Motorrad ist. Die Aussage der abstrakten Methodendeklaration ist also quasi "Alle Fahrzeuge können losfahren. Wie, ist mir egal."
Und wo muss das rein?
Ein Interface kannst du dir vereinfacht vorstellen als eine abstrakte Klasse, die nur abstrakte Methoden und sonst nichts enthält. Zusätzlich ist der Unterschied, dass Interfaces nicht mit "extends", sondern mit "implements" eingebunden werden, und dass eine Klasse mehrere Interfaces einbinden kann.
Um Struktur zu schaffen ?

EDIT:


Was ne Referenz ist hab ich noch nicht ganz verstanden.

Wenn ne Instanz vom Typ Beamter ist und Beamter von der Klasse Person abgeleitet wird, dann kann die Instanz die Methoden von Beamter und von Person aufrufen.
GANZ GLEICH was der Instanz für ne Referenz zugewiesen wurde.

Dabei biegst du allerdings die Referenz um
Hurra, ich habe die Referenz geändert. Die Instanz ist aber immernoch vom selben Typ und kann immernoch diesleben Methoden aufrufen. Geändert hat sich für mich nix.
 
Zuletzt bearbeitet:
Mal ein Beispiel zum Thema abstrakte Methoden, dann wird's wohl klarer:

PHP:
abstract class Fahrzeug {
    // Ja, public oder protected kommt mit dazu. private wäre hier natürlich sehr sinnlos.
    abstract public void losfahren(); // beachte das Semikolon statt der geschweiften Klammern
}

class Auto extends Fahrzeug {
    // es gehört in Java zum "guten Ton", @Override dranzuschreiben, wenn man eine Methode
    // aus der Oberklasse implementiert
    @Override
    public void losfahren() { // hier kein abstract
        // tu etwas
    }
}

Das heißt also: Die abstrakte Deklaration kommt in die abstrakte Oberklasse, die konkrete Implementation (ja, "konkret" heißt einfach "nicht abstrakt" :)) dementsprechend in die konkrete Unterklasse.

Danach kannst du auf jeder Fahrzeug-Referenz losfahren() aufrufen, ohne zu wissen, was genau für ein Objekt dahinterliegt.

Edit: Ich sollte echt mal ein kleines E-Book schreiben, "Objektorientierung für Einsteiger" :D
 
Zuletzt bearbeitet:
Bitte meinen Edit aus Post 27 lesen.
der Thread hätte sicher doppelt so viele Posts wenn nicht jeder von uns seinen post xmal editieren würde.

Gut, es ergibt sinn.

Wenn man ne Instanz von Moped, Auto, Motorrad deklarieren will muss die Methode losfahren vorhanden sein, weil das die Klasse Fahrzeug so vorschreibt.

ohne zu wissen, was genau für ein Objekt dahinterliegt.
Aber ich weiß doch immer was für ein Objekt(wieso hast du nicht Instanz geschrieben) dahinerliegt, nämlich Moped, Auto, Motorred, etc.

es gehört in Java zum "guten Ton",
Über Semantik kann ich mir später den Kopf zerbrechen. :D

Edit: Ich sollte echt mal ein kleines E-Book schreiben, "Objektorientierung für Einsteiger" :D
Ich würde es vorbestellen. :D
Oder du druckst einfach den ganzen Thread aus. :D

ich mach jetzt erstmal feierabend und lerne dann heute abend weiter.
bis dahin fallen mir sicher einige nette fragen ein. :)
 
Zuletzt bearbeitet:
It'sNever2Late! schrieb:
Aber ich weiß doch immer was für ein Objekt(wieso hast du nicht Instanz geschrieben) dahinerliegt, nämlich Moped, Auto, Motorred, etc.

Wenn du das Objekt selbst angelegt hast, ja. Aber vielleicht hast du das ja gar nicht, sondern du bekommst es von irgendwo anders - und weißt dabei nur, dass es ein Fahrzeug ist. Du könntest zum Beispiel eine Funktion schreiben, die eine Liste von Fahrzeugen übergeben bekommt (sagen wir, alle Fahrzeuge auf einem Parkplatz - da stehen Autos. Motorräder und vielleicht noch andere Vehikel) und mit allen Elementen dieser Liste etwas macht:

PHP:
public void alleLosfahren(List<Fahrzeug> fahrzeuge) {
    for (Fahrzeug fahrzeug : fahrzeuge) {
        fahrzeug.losfahren();
    }
}
 
Also ich habe jetzt ein kleines Programm mit Konstruktor und abgeleiteten Klassen und abstrakten Methoden erstellt und meine auch, dass alles richtig ist. Ich habe zwar einen Fehler, jedoch hat der nichts mit dem besprochenen hier zu tun.

Folgender Code:
Fahrzeug.java:
PHP:
// Klasse Scanner wird importiert um Benutzereingaben zu ermöglichen
import java.util.Scanner;
abstract class Fahrzeug {
  // "protected" anzahlRaeder und durchschnittsGeschwindigkeit werden "leer" deklariert
  protected int anzahlRaeder;
  protected int durchschnittsGeschwindigkeit;
  protected int kiloMeterStand;

  // Konstruktor
  // Beim Aufruf der Methode super einer abgeleiteten Klasse wird diese Methode aufgerufen
  // Und die Instanz bekommt die Argumente als "Objektglieder"
  public Fahrzeug(int raeder, int geschw, int kilo) {
    this.anzahlRaeder = raeder;
    this.durchschnittsGeschwindigkeit = geschw;
    this.kiloMeterStand = kilo;
  }

  // abstracte Methode, die in allen anderen abgeleiteten Klassen vorhanden sein muss
  abstract public void losFahren(int newkilo);

  // Main Funktion
  public static void main(final String[] args){
    Scanner input = new Scanner(System.in);
    int a,b,c;
    String g;

    // Benutzer entscheidet was fuer ein neues Fahrzeug er haben moechte
    System.out.println("Mit welchem Fahrzeug moechten Sie eine kleine Spritztour machen? ");
    System.out.println("Auto\t\tMercedes\t1");
    System.out.println("Motorrad\tBMW\t\t2");
    System.out.println("Moped\t\tHerkules\t3");
    System.out.print("Fahrzeug: ");
    a = input.nextInt();
    if((a < 0) || (a > 3)){
      System.out.println("Sie haben ein ungueltiges Fahrzeug gewaehlt...");
      System.exit(0);
    }
    System.out.print("Soll ihr Fahrzeug schnell oder langsam sein? [schnell/langsam] ");
    g = input.nextLine();
    if(g.equals("schnell")) c = 120;
    else c = 60;
    System.out.print("Und wie weit wollen Sie mir Ihrem Fahrzeug fahren? ");
    b = input.nextInt();
    switch(a){
      case 1: Auto mercedes = new Auto(c);
              mercedes.losFahren(b);
              break;
      case 2: Motorrad bmw = new Motorrad(c);
              bmw.losFahren(b);
              break;
      case 3: Moped herkules = new Moped(c);
              herkules.losFahren(b);
              break;
    }
  }
}
Auto.java:
PHP:
class Auto extends Fahrzeug {
  public Auto(int geschw) {
    super(4, geschw,60000);
  }

  @Override
  public void losFahren(int newkilo){
    this.kiloMeterStand += newkilo;
    System.out.println("Der Kilometerstand ihres Autos liegt nun bei " + kiloMeterStand);
  }

}
Motorrad.java:
PHP:
class Motorrad extends Fahrzeug {
  public Motorrad(int geschw) {
    super(2, geschw,20000);
  }

  @Override
  public void losFahren(int newkilo){
    this.kiloMeterStand += newkilo;
    System.out.println("Der Kilometerstand ihres Motorrads liegt nun bei " + kiloMeterStand);
  }
}
Moped.java:
PHP:
class Moped extends Fahrzeug {
  public Moped(int geschw) {
    super(2, geschw,1600);
  }

  @Override
  public void losFahren(int newkilo){
    this.kiloMeterStand += newkilo;
    System.out.println("Der Kilometerstand ihres Mopeds liegt nun bei " + kiloMeterStand);
  }
}


Ich bekomme noch einen kleinen Fehler, und zwar gibt er mir in Zeilen 39 und 43 die beiden System.outs aus, noch bevor die Eingabe g = input.nextLine(); stattfinden konnte. Nach Eingabe (wobei ich nicht wissen kann ob ich einen String oder Int eingeben muss) bekomme ich natürlich einen Fehler.
 
Zuletzt bearbeitet:
Das liegt am Verhalten von nextInt(). Scanner.nextInt() liest nur das nächste Token ein, also die nächste Zahl bis zu einem Trennzeichen (im Normalfall das Leerzeichen, aber auch das newLine von Enter), lässt aber den Rest der Zeile noch stehen. D.h. die Eingabe sieht so aus:

Ausgabe: Mit welchem Fahrzeug moechten Sie eine kleine Spritztour machen?
Eingabe: 1\n

nextInt() liest jetzt die 1 aus, lässt aber das "\n" noch stehen, weil es damit nix anfangen kann. Wenn du jetzt Scanner.nextLine() ausführst, sieht er dass da noch ein "\n" steht. Er liest das Zeichen, und damit die gesamte Zeile ein und ist mit seinem Input fertig. Deshalb überspringt er die erste Eingabe und geht direkt zur Ausgabe von System.out.print("Und wie weit wollen Sie mir Ihrem Fahrzeug fahren? "); weiter und fragt nach einer anderen Eingabe.
Die vermutlich einfachste Möglichkeit das zu umgehen ist statt nextLine() einfach next() zu verwenden. Scanner.next() sucht einfach nach dem nächsten richtigen Token.
 
Kann ich denn System.next() immer anstelle von nextInt() und nextLine() verwenden?
 
Könntest du, kommt aber auf den Einsatzzweck an.

next() gibt dir immer das nächste Token als String zurück, nextInt() gibt dir das Token als int zurück, nextDouble() als Double usw. ( vorausgesetzt das Token kann als solches interpretiert werden)

nextLine() gibt dir den Rest aus ab dem nächsten Token, lässt aber den line.separertor weg und setzt dich auf die nächste Zeile.
 
Zuletzt bearbeitet:
Du kannst es im Grunde überall da benutzen, wo du auch nextLine() nutzt. Ein Fall wo es nicht so klappt wäre allerdings, wenn du nextLine() benutzt um z.B. einen ganzen Satz einzulesen. Das müsstest du wenn dann mit mehreren next() realisieren.
 
Gut, ich habe das nextLine() durch next() ersetzt und die nextInt()s so gelassen und es funktioniert.

Jetzt habe ich noch eine Frage.

In der abstrakten Methode losFahren einer abgeleiteten Klasse wird this.kiloMeterStand erhöht.

Aber wenn ich diese Methdode 2mal aufrufe wird kiloMeterStand immer auf den Standardwert zurückgesetzt und nicht mehrfach erhöht, siehe:

PHP:
    while(true){
      // Benutzer entscheidet was fuer ein neues Fahrzeug er haben moechte
      System.out.println("Mit welchem Fahrzeug moechten Sie eine kleine Spritztour machen? ");
      System.out.println("Auto\t\tMercedes\t1");
      System.out.println("Motorrad\tBMW\t\t2");
      System.out.println("Moped\t\tHerkules\t3");
      System.out.print("Fahrzeug: ");
      a = input.nextInt();
      if((a < 0) || (a > 3)){
        System.out.println("Sie haben ein ungueltiges Fahrzeug gewaehlt...");
        System.exit(0);
      }
      System.out.print("Soll ihr Fahrzeug schnell oder langsam sein? [schnell/langsam] ");
      g = input.next();
      if(g.equals("schnell")) c = 120;
      else c = 60;
      System.out.print("Und wie weit wollen Sie mir Ihrem Fahrzeug fahren? ");
      b = input.nextInt();
      switch(a){
        case 1: Auto mercedes = new Auto(c);
                mercedes.losFahren(b);
                break;
        case 2: Motorrad bmw = new Motorrad(c);
                bmw.losFahren(b);
                break;
        case 3: Moped herkules = new Moped(c);
                herkules.losFahren(b);
                break;
      }
    }

Nach dem losFahren wähle ich wieder das Fahrzeug und die zurückzulegende Strecke aus, diese (also Variable b) wird immer wieder auf den Standard-wert addiert.
Ich hatte aber gehofft kiloMeterStand einer Instanz dauerhaft (und mehrfach ) verändern/erhöhen kann.

Ich glaube mein Denkfehler liegt darin, dass innerhalb der switch-case Funktion die Instanz neu erstellt/deklariert wird, nur wie soll ich das anders lösen?
Ich muss die while-schleife so ändern, dass ich immer wieder aufs neue ein fahrzeug, dessen geschwindigkeit und die zurückzulegende strecke eingeben kann ohne die instanz immer wieder neu zu erstellen.

Oder habe ich einen fataleren Denkfehler?

Edit:
Eine sache habe ich lieder immer noch nicht ganz so richtig verstanden.
Referenz
PHP:
Person mutter = new Person();
Person vater = new Beamter();
mutter ist eine Instanz der Klasse Person mit der Referenz auf die Klasse Person und kann auch nur die Methoden der Klasse Person aufrufen.
vater hingegen ist eine Instanz der Klasse Person mit der Referenz auf die Klasse Beamter und kann die Methoden welcher Klasse aufrufen? (ich weiß es nicht und vermute nur Person)
PHP:
Beamter vater = new Beamter();
vater ist eine Instanz der Klasse Beamter mit der Referenz auf die Klasse Beamte rund kann alle Methoden der Klasse Beamter und (weil Beamter extends Person) auch die Methoden der Klasse Person aufrufen.
PHP:
Beamter vater = new Person();
ERROR (-Compiler)

Und was ist wenn ich später aus
PHP:
Person vater = new Beamter();
folgendes mache:
PHP:
vater = new Rentner();
Beamter und Rentner extends person natürlich

Die Referenz ändert sich, aber die vorhandenen und aufrufbereiten Methoden bleiben gleich/ändern sich nicht.
 
Zuletzt bearbeitet:
Deine Bezeichnungen verwirren mich etwas. :D

Das siehst du schon richtig. Solang deine Referenz vom Typ Person ist, kannst du (egal was für eine Instanz tatsächlich dahinter steckt) die entsprechenden Methoden von Person aufrufen. Willst du hingegen dann auf dem Vater eine Funktion der Rentnerklasse aufrufen, dann castest du an der Stelle.
Code:
((Rentner) vater).roecheln();
Edit: Noch zu deiner Frage davor - du erstellst einfach deine Referenzen auf die Instanzen der Fahrzeuge schon vorher, initialisierst sie aber mit null. Dann kannst du in der switch checken ob
Code:
if (mercedes == null)
    mercedes = new Auto(c);
mercedes.losFahren(b);
...
Oder du initialisierst generell jedes Fahrzeug schon vorher und nimmst in Kauf, dass manche davon nicht benutzt werden. Ist aber weniger elegant.
Hoffe ich habe jetzt nichts übersehen. Habe nicht alles davor gelesen hier. ;)
 
Zuletzt bearbeitet:
Und dabei ist es egal ob vater eine Instanz der Klasse Person oder Beamter ist?

Neben der Tatsache, dass ihr auch unterschiedliche Bezeichnungen verwendet (bsp nennst du ne Instanz wieder Referenz, was mich verwirrt)) möchte ich schlichtweg den Unterschied zwischen folgendem vertehen:

PHP:
Beamter extends Person();

    // Instanz vater der Klasse Person mit Referenz auf Person
    Person vater = new Person();
    
    // Instanz vater der Klasse Person mit Referenz auf Beamter
    Person vater = new Beamter();
    
    // Instanz vater der Klasse Beamter mit Referenz auf Beamter
    Beamter vater = new Beamter();
    
    // Instanz vater der Klasse Beamter mit Referenz auf Person
    Beamter vater = new Person();

Das verwirrt mich gerade am meisten.
Was ist richtig, was falsch, was darf was machen und was darf wessen methoden ohne casten aufrufen?

EDIT:
Also so:
PHP:
  // Main Funktion
  public static void main(final String[] args){
    Scanner input = new Scanner(System.in);
    int a,b,c;
    String g;
    Auto mercedes = null;
    Motorrad bmw = null;
    Moped herkules = null;

    while(true){
      // Benutzer entscheidet was fuer ein neues Fahrzeug er haben moechte
      System.out.println("Mit welchem Fahrzeug moechten Sie eine kleine Spritztour machen? ");
      System.out.println("Auto\t\tMercedes\t1");
      System.out.println("Motorrad\tBMW\t\t2");
      System.out.println("Moped\t\tHerkules\t3");
      System.out.print("Fahrzeug: ");
      a = input.nextInt();
      if((a < 0) || (a > 3)){
        System.out.println("Sie haben ein ungueltiges Fahrzeug gewaehlt...");
        System.exit(0);
      }
      System.out.print("Soll ihr Fahrzeug schnell oder langsam sein? [schnell/langsam] ");
      g = input.next();
      if(g.equals("schnell")) c = 120;
      else c = 60;

      System.out.print("Und wie weit wollen Sie mir Ihrem Fahrzeug fahren? ");
      b = input.nextInt();
      switch(a){
        case 1: if(mercedes == null) mercedes = new Auto(c);
                mercedes.losFahren(b);
                break;
        case 2: if(bmw == null) bmw = new Motorrad(c);
                bmw.losFahren(b);
                break;
        case 3: if(herkules == null) herkules = new Moped(c);
                herkules.losFahren(b);
                break;
      }
    }
  }
 
Zuletzt bearbeitet:
It'sNever2Late! schrieb:
vater hingegen ist eine Instanz der Klasse Person mit der Referenz auf die Klasse Beamter und kann die Methoden welcher Klasse aufrufen? (ich weiß es nicht und vermute nur Person)

Vater ist eine Referenzvariable vom Typ Person, welche auf eine Instanz des Typs Beamter verweist. Du kannst darauf die Methoden aufrufen, die der Typ Person veröffentlicht. Wenn deine Beamtenklasse Methoden der Person überschreibt (beispielsweise wenn beide eine Methode 'Hallo' jaben), dann ruft du trotzdem die Implementierung aus Beamter und nicht aus Person auf (Late binding). Der Überbegriff für das ganze ist Polymorphie, evt. hilft dir das bei deiner Recherche.

It'sNever2Late! schrieb:
PHP:
Beamter vater = new Person();
ERROR (-Compiler)

Beamter ist ein speziellerer Typ als Person, das geht so nicht. Denn du könntest auf Vater ja alle Methode aufrufen, welche in Beamter veröffentlicht werden - aber Person als allgemeinerer Typ besitzt diese vielleicht ja gar nicht.
 
Zuletzt bearbeitet:
Das letzte geht nicht, Rest geht so. Die Person ist ja die Wurzel der Hierarchie, daher darf alles was davon erbt auch rechts initialisiert werden.
Beamter links und rechts geht auch, weil auf gleichem level.

Mal zu den Begrifflichkeiten. Für mich ist

Person vater =...

eine Referenz auf die Instanz/Objektinstanz/ein Objekt der Klasse Person. Das schließt auch alle ein, die die Klasse Person erweitern (davon erben, extends). vater "zeigt" also auf so eine Instanz. Darfst das aber nicht wörtlich nehmen, denn das könnte jemand der pingelig ist mit Zeigern/Pointern und Referenzen z.B. in C++ verdrehen und da gibt es dann einen Unterschied.

Mir sind jedenfalls noch keine abweichenden Bezeichnungen untergekommen.
 
Zuletzt bearbeitet:
Zurück
Oben