Java Dreieck Flächenberechnung mit Getter/Setter

  • Ersteller Ersteller evenstar4118
  • Erstellt am Erstellt am
E

evenstar4118

Gast
Hey Leute,

ich sitze seit einigen Tagen an einer Aufgabe und komm einfach nicht weiter. Ich habe mich mehrere Stunden mit Tutorial Videos, Vorlesungsskript und sonstigen Informationsquellen beschäftigt! Ich seh wohl mittlerweile den Wald vor lauter Bäumen nicht...

Und nur um das klarzustellen: Ich will das verstehen was ich da mache! Und vielleicht hilft mir der ein oder andere Link weiter! Oder vielleicht kann der ein oder andere in seinen eigenen Worten beschreiben wie das funktioniert... das wäre echt super!

Hier erstmal die Aufgabenstellung und das, was ich ich bisher gemacht habe:

Aufgabe --> 3 Klassen erstellen (TestGeo, Punkt, Dreieck), 3 vorgegebene Punkte sollen zu einem Dreieck konstruiert werden bzw. dessen Fläche berechnet werden. Und als kleiner Zusatzpunkt soll, wenn Fläche <0 ist, eine Fehlermeldung ausgegeben werden.

Hier mein bisheriger Code:

Code:
package geo;

public class TestGeo {

	public static void main(String[] args) {

		Punkt P1 = new Punkt(0, 10);
		Punkt P2 = new Punkt(5, 5);
		Punkt P3 = new Punkt(10, 5);

		Dreieck D1 = new Dreieck();

		System.out.println(P1.getX());

	}

}

Code:
package geo;

class Punkt {

	private int x;
	private int y;

	public Punkt(int wertX, int wertY) {

		x = wertX;
		y = wertY;

	}

	public void setX(int x) {
		this.x = x;
	}

	public int getX() {
		return this.x;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getY() {
		return this.y;
	}

}

Code:
package geo;

class Dreieck {

	// Soll auf Punkte Zugreifen
	// Konstruktor berechnet Fläche

}

Irgendwie hab ich einfach nen Knoten im Hirn wegen dieser Flächenberechnung. In den TutorialVideos versteh ichs zumindest halbwegs, aber da gehts nicht um Dreiecke sondern Autos, Menschen etc.

Wenn mir irgendjemand in eigenen Worten das etwas erklären könnte, wie getter/setter genau funktionieren, oder einen Tipp hat, wie ich das Programm zum laufen bekomme, wäre echt mehr als Klasse!

Wie schon gesagt, ich will nicht das Ihr hier meine "Hausaufgaben" macht! Ich will das verstehen und einen fertigen Code über Copy/Paste bringt mir nichts.

vielen Dank schonmal im Vorraus!

mfg
 
damit das Dreieck weiss welche Punkte es benutzt wäre es wohl am einfachsten beim erzeugen des Dreiecks gleich die Punkte mit zu übergeben

das heißt du würdest bei Dreieck den Konstruktor so aufbauen wie du es auch bei Punkten gemacht hast, nur machst du es da nicht mit :

int WertX, int WertY sondern mit: Punkt punktA, Punkt punktB, Punkt punktC
das was du dann übergibst schreibst du in die Eigenschaften des Dreiecks (hast du ja bei Punkt auch schon mit X und Y gemacht)

in der TestGeo kannst du dann sagen, dreieck.getPunktA genau so B und C und dann die Fläche berechnen
wobei es wahrscheinlich sogar mehr SInn macht die Berechnung der Fläche auch in der Klasse Dreieck zu machen und das Ergebnis als zusätzliche Eigenschaft des Dreiecks zur Verfügung zu stellen

Noch kurz zu den Getter/Settern:
sinn dieser Methoden ist das du so Kontrollieren kannst wer/was auf die Eigenschaften eines Objektes zugreifen darf

angenommen wir haben eine Ampel, die hat mit sicherheit ne eigenschaft:
istAn = true/false (also ist die Ampel an oder aus)
farbe = grün/gelb/rot (welche Farbe leuchtet gerade)

jetzt wäre es natürlich absolut fatal wenn jeder die Farbe der Ampel ändern könnte,
das wäre möglich wenn die eigenschaft Farbe public wäre. dann könnte ich wenn ich auf die Kreuzung zu fahre die Ampel einfach auf grün stellen und fahren, das könntest du aber auch machen wenn du aus einer anderen Richtung auf die Ampel zu fährst , was dann natürlich Chaos auf der Kreuzung verursachen würde

damit würdest du die eigenschaft farbe private setzen (diese Eigenschaft ist nun für niemanden mehr zu sehen, außer innerhalb des Objekts selber) , das ist natürlich auch nicht sinnvoll, da wenn wir beide nun auf die Kreuzung zu fahren keiner weiss was nun an ist.
darum spendierst du einen getter getFarbe(), wenn ich auf die Krezuung zu fahre, bekomme ich von der Methode die antwort: ROT, ich bleibe stehe, wenn du die methode aufrufst bekommst du GRÜN und du darfst fahren

jetzt ist diese Eigenschaft sicher vor veränderungen, wenn du aber möchtest das eine eigenschaft geändert werden kann dann macht man das mit einer Methode die Setter heißt

GETTER - get - Wert Bekommen
SETTER - set - Wert Setzen
 
Zuletzt bearbeitet von einem Moderator:
Du kannst die setter beim Punkt eigentlich weglassen. Die Veränderbarkeit der Koordinaten bringt nur Verwirrung, wenn da zur Laufzeit dran rumgespielt werden kann. Die Koordinaten werden ja bei Erstellung des Punkts gesetzt (per Konstruktor).


Beim Punkt hast du ja schon einen Konstruktor und verwendest ihn, um die Koordinaten zu setzen. Das gleiche Prinzip überträgst du nun auf das Dreieck, nur dass das Dreieck eben 3 Objekte der Klasse Punkt hält, statt ints. Neben den 3 Feldern (oder eine Liste/ein Array, das ist dir überlassen) der Punkte, die zum Dreieck gehören, kann es dann noch ein Feld für den Flächeninhalt geben, was eben im Konstruktor direkt berechnet und gesetzt wird. Dafür sollte es dann natürlich im Dreieck noch einen getter geben, der den Wert abrufen kann und auch hier macht ein setter überhaupt keinen Sinn. Der Wert sollte sogar "final" (konstant) gesetzt werden, aber das hattet ihr vermutlich noch nicht.
 
Mittels Getter und Setter greifst du einfach auf die Variablen anstatt sie direkt anzusprechen.

Du legst einen neuen Punkt an, indem du im Konstruktor direkt die Werte für X und Y übergibst. Du könntest aber auch den Standardkonstruktor aufrufen und dann mittels setX(...), setY(...) die Werte festlegen.
Also anstatt
Code:
Punkt P1 = new Punkt(0, 10);
einfach
Code:
Punkt p1 = new Punkt();
p1.setX(5);
p1.setY(5);

Um nun herauszufinden welche Werte X und Y von p1 haben kannst du diese mittels
Code:
p1.getX();
und
Code:
p1.gety()
abfragen.

Du hast in TestGeo nun 3 Punkte erzeugt die das Dreieck bilden sollen. Dazu musst du diese Punkte nun dem Dreieck übergeben. Das kannst du z. B. wieder über den Konstruktor machen wie du es schon bei den Punkten gemacht hast. Dazu musst du in der Dreieck-Klasse die entsprechenden Variablen definieren, Getter und Setter schreiben und einen entsprechenden Konstruktor. Und dann kannst du innerhalb der Dreieck-Klasse die Flächenberechnung durchführen.
 
Ich versuche das mal halbwegs komplett zu erklären, bin zwar kein Java Pro aber sollte genug wissen ^^

Class TestGeo:
Beeinhaltet die main methode, also das wo es los geht wenn man das Programm startet.

Zeile 7-9:
Es werden neue Instanzen der Klasse Punkt erzeugt.
Das "new Punkt(0, 10)" ruft den Konstruktor der Klasse Punkt auf, also die Methode die so heißt wie die Klasse selbst.
Da mit 0 und 10 zwei int (Ganzzahlen) übergeben werden, muss die Klasse Punkt einen Konstruktor haben der zwei int als Parameter entgegen nimmt - übergibst du Parameter für den es keinen entsprechenden Konstruktor gibt, bekommst du sofort einen Fehler angezeigt. Es kann auch mehrere Konstruktoren geben, leere, einen mit drei ints usw. Hier werden deine übergebenen Zahlen 0 und 10 den private Variablen zugewiesen.

Instanziierungen sind simpel gesagt einfach nur Kopien, jede Instanziierung hat somit "eigene" geklonte Methoden und Variablen der Klasse Punkt, dies passiert sobald du "new...." schreibst. Sollte man wissen, da du mehrere Punkt über die gleiche Klasse instanziierst und jeder Punkt seine eigenen, verschiedenen Koordinaten haben können muss ... :D Ist praktisch die Grundidee der Objektorientierten Programmierung, eine Klasse schreiben und beliebig oft für anderes Zeugs benutzen.

Zeile 11:
Instanziierung der Klasse Dreieck, aufruf des Dreieck Konstruktors ohne Parameter Übergabe, also von Dreieck() {}

Zeile 13:
Ausgabe des Rückgabewertes getX() welches mit P1 instanziiert wurde.

-----------------

Class Punkt:
Zeile 8-13: Der Konstruktor der in der main durch "new Punkt(0,10)" aufgerufen wurde. Hier werden nun die oben deklarierten Variablen zugewiesen.
Ab hier wird es wichtig wegen dem getter und setter. Da du die Variablen in Zeile 5+6 als private deklariert hast, können diese außerhalb der Klasse nicht gesehen werden! Du kannst sie also nicht direkt aus TestGeo aufrufen.

Zeile 15-29:
Public Methoden, diese können also von außerhalb gesehen werden. Da sich diese Methoden mit den private Variablen in der gleichen Klasse befinden, sehen sich diese Methoden und Variablen. Nun kannst du in TestGeo auf eine dieser Methoden zugreifen und dir darüber die private Variablen holen !
Du fragst also die Methode getX() nach der Variablen "private x" seiner Klasse.

GetX holt dir also diese Variablen, SetX setze diese.
P1.getX() ruft also die Kopie der Methode getX() auf, die nun in P1 steckt (ensteht bei dem new....).
Nochmal: P2 usw. hat seine eigenen Variablen und Methoden als Kopie. Wäre dies nicht so, würden sich die x,y Variablen für P1-P3 ändern sobald du P1 änderst.

Der Sinn der Geschichte ist, dass du nicht direkt x und y sehen kannst. Z.b. zahlst du in der Bank auf ein Fremdkonto ein. Statt den Betrag zu sehen und deine Einzahlung direkt zu verrechnen, übergibst dem Banker (der getX , setX) das Geld, dieser verrechnet es ohne dass du weißt was hinter den Kulissen passiert.

----------

Dreieck:
Mit P1.getX(), P1.getY(), P2.getX() usw... kannst die jeweiligen Koordinaten jedes "Punkt" Klons/Instanz holen.
In der Klasse Dreieck kannst dann z.B. die Methode "public int Flaeche(Punkt P1, Punkt P2, Punkt P3) { } schreiben. Diese kannst du von der main Methode aus mit D1.Flaeche(P1, P2, P3) aufrufen.
Innerhalb der Flaeche() Methode kennt man dann auch ein P1.getX() und du kannst rechnen. Das Erebnis geht dann per return zurück an die Stelle des Aufrufs und steht dann an der Stelle wo der Methodenaufruf stand, praktisch wie ersetzt mit dem Ergebnis. Da ein System.out drum rum ist, wird das Ergebnis ausgegeben ;)

Du KANNST dir noch die Fälle überlegen in denen es keine Fläche gibt. Mal dir am besten ein Dreieck auf Papier und schieb die Punkte/Ecken rum ;) Eine entsprechende If-Abfrage um sich unnötige Rechenzeit zu sparen wäre doch was. Kannst aber auch immer berechnen lassen und die Fläche am Ende prüfen.

Hattet ihr schon Vektoren? Damit könntest du die Fläche ausrechnen, aber vielleicht geht es auch einfacher.
http://www.youtube.com/watch?v=qnTFQgzf5dY
 
Zuletzt bearbeitet:
Ich muss mich gerade sowieso wieder an Java gewöhnen und habe dir das mal eben ausprogrammiert. Erklärt wurden die Prinzipien ja schon.

Code:
package geo;

public class Dreieck {
	
	private Punkt p1, p2, p3;
	private Float f;
	
	public Dreieck(Punkt p1, Punkt p2, Punkt p3) {
		this.p1 = p1;
		this.p2 = p2;
		this.p3 = p3;
		f =  0.5f * (p1.getX() * ( p2.getY() - p3.getY() ) +
				p2.getX() * ( p3.getY() - p1.getY() ) +
				p3.getX() * ( p1.getY() - p2.getY() ));
	}

	public Punkt getP1() {
		return p1;
	}

	public Punkt getP2() {
		return p2;
	}

	public Punkt getP3() {
		return p3;
	}

	public float getF() {
		return f;
	}
}

Code:
package geo;

public class TestGeo {

	public static void main(String[] args) {
		 
		Punkt p1 = new Punkt(0f, 10f);
		Punkt p2 = new Punkt(5f, 5f);
		Punkt p3 = new Punkt(10f, 5f);
 
		Dreieck d1 = new Dreieck(p1, p2, p3);
		Float f = d1.getF();
		
		if(f < 0f) {
			System.out.println("Fläche < 0..");
		} else {
			System.out.println(f);
	
		}
	}
}

Ich habe der Einfachheit halber alle Variablen auf Float umgestellt, damit nicht gecastet werden muss. Allgemein schreibt man Variablennamen übrigens klein.
Die Formel, die ich zur Berechnung der Fläche eines Dreickes verwendet habe, findest du hier:
http://de.wikipedia.org/wiki/Dreiecksfläche#In_der_Ebene

Das Ergebnis für dieses Dreieck ist 12,5.
 
Zuletzt bearbeitet:
Ich denke Burfi hier hat das Dreieck ganz sauber implementiert. Man kann dann noch überlegen ob man die "getter" Methoden für die Punkte überhaupt braucht.

Verwendet man die Dreieck Klasse von Burfi, so würde deine Main-Methode dann so aussehen:

Code:
    package geo;
     
    public class TestGeo {
     
    public static void main(String[] args) {
     
       Punkt P1 = new Punkt(0, 10);
       Punkt P2 = new Punkt(5, 5);
       Punkt P3 = new Punkt(10, 5);
     
       Dreieck D1 = new Dreieck(P1, P2, P3); // man übergiebt die 3 punkte dem konstruktor von dreieck, und der konstruktor berechnet dann die fläche
     
       // ausgabe der fläche auf der konsole
       System.out.println("Die Fläche beträgt: " + D1.getF());
     
    }
     
    }
 
Ich habe das so verstanden, dass dies bei ihm zur Aufgabenstellung dazu gehört. Ich würde es normalerweise auch in einer eigenen Methode machen, die dann entsprechend den Wert zurück gibt. So müsste dieser nicht im Objekt gespeichert werden.
 
Vielen Dank an Euch alle erst mal für die ausführlichen Beschreibungen!! Ich brauch jetzt erst mal n bisschen um mich da durchzuarbeiten :D
Was mich irgendwie zu schaffen gemacht hat, war die Flächenberechnung ansich! Ich hab da viel zu viel nachgedacht und nicht einfach gemacht! Im Endeffekt zeigt mir das alles aber, das ich wohl noch nicht genug programmiere!

Ich hab bisher die Erfahrung gemacht das die Aneignung von einer Anweisungen/Thema (z.B.: Rekursion) am Anfang ziemlich schwierig sind zu verstehen. Ich hab wirklich Stunden gebraucht um das zu verstehen und vor allem es dann auch ohne Probleme anwenden zu können!

Ich werd mich jetzt mal dranmachen und die Aufgabe noch komplettieren und wie schon gesagt, das Ding durchgehen und verstehen :)

Falls ich nochmal Fragen hab, werd ich mich auf jedenfall nochmal melden!
Ergänzung ()

Was genau meint Ihr mit nicht im Konstruktor machen, sondern auslagern? Die Flächenberechnung?

Also im Endeffekt ist es mir überlassen wie das Ding am Ende aufgebaut ist, ich hab lediglich die Vorgaben mit Klassen und getter/setter erstellen sowie Anwenden von Konstruktoren.

Du meinst eine eigene Methode zur Flächenberechnung?
 
Ja. Also einfach die 3 Punkte im Konstruktor übergeben (was in meinem ja auch passiert).

Die Berechnung aus meinem Beispiel dann einfach in eigene Methode, sodass diese direkt von außern gerufen werden kann. Dadurch wird die Klassenvariable "f" in meinem Beispiel unnötig.
 
So, ich poste jetzt mal das fertige Programm! Das ganze mit 9 Punkten realisiert... es funktioniert, aber ich hab vermutlich noch einige redundante Sachen drin...

Code:
package geo;

public class TestGeo {

	public static void main(String[] args) {

		Punkt p1 = new Punkt(0,10);
		Punkt p2 = new Punkt(5,5);
		Punkt p3 = new Punkt(10,5);
		Punkt p4 = new Punkt(15,10);
		Punkt p5 = new Punkt(20,0);
		Punkt p6 = new Punkt(-5,5);
		Punkt p7 = new Punkt(-15,5);
		Punkt p8 = new Punkt(-15,-5);
		Punkt p9 = new Punkt(0,-5);

		Dreieck d1 = new Dreieck(p1, p2, p3);
		double z = d1.getZ();

		Dreieck d2 = new Dreieck(p3, p4, p5);
		double v = d2.getV();
		
		Dreieck d3 = new Dreieck(p7, p8, p9);
		double o = d3.getO();
		
		
		if ((z < 0)|(v < 0)|(o < 0)) {

			System.out.println("Die Fläche ist < 0 --> ungültige Eingabe");
			
		} else {

			System.out.println("Die Fläche von D1 ist " + z);
			System.out.println("Die Fläche von D2 ist " + v);
			System.out.println("Die Fläche von D3 ist " + o);

		}

	}

Code:
package geo;

class Punkt {

	private double x;
	private double y;

	public Punkt(double wertX, double wertY) {

		x = wertX;
		y = wertY;

	}

	public void setX(double x) {
		this.x = x;
	}

	public double getX() {
		return this.x;
	}

	public void setY(double y) {
		this.y = y;
	}

	public double getY() {
		return this.y;
	}

}

Code:
package geo;

class Dreieck {

		private Punkt a, b, c;
		private double z, v, o;
		
	public Dreieck (Punkt punktA, Punkt punktB, Punkt punktC){
		
		this.a = punktA;
		this.b = punktB;
		this.c = punktC;
		
		z = v = o = 0.5 * (a.getX() * b.getY() - c.getY())
						+ (b.getX() * c.getY() - a.getY())
						+ (c.getX() * a.getY() - b.getY());
		
	}

	public double getV() {
		return v;
	}

	public double getO() {
		return o;
	}

	public Punkt getA() {
		return a;
	}

	public Punkt getB() {
		return b;
	}

	public Punkt getC() {
		return c;
	}
	
	public double getZ() {
		return z;
	}
	
}


Das mit der eigenen Methode werd ich mir jetzt nochmal anschauen
 
Moin!

Schmeiß aus deiner Klasse die Variablen z, v und o raus. Und entferne die Berechnung der Fläche aus dem Konstruktor. Dieser dient nur der Initialisierung und keiner weiteren Aufgabe (Stichwort single responsibility principle)

--> Berechnung der Fläche in eigene Methode auslagern:

Code:
public double calculateArea() {
  // Berechnung der Fläche
}

In der Testklasse rufst du dann einfach diese Methode für die jeweiligen Dreiecke auf!
 
Zuletzt bearbeitet:
Ich würde den Aufruf der methode schon im konstruktor machen und die Methode private.
Warum sollte die Berechnung von außen angestoßen werden?
Das wird einmal bei Erzeugung gemacht .
 
Kann man natürlich private machen. Dann aber eine public-Methode getArea()
 
mach es so:

Code:
 package geo;
     
    class Dreieck {
     
    private Punkt a, b, c;
    public Dreieck (Punkt punktA, Punkt punktB, Punkt punktC){
    this.a = punktA;
    this.b = punktB;
    this.c = punktC;
    }
     
    public Punkt getA() {
    return a;
    }
     
    public Punkt getB() {
    return b;
    }
     
    public Punkt getC() {
    return c;
    }
    public double calculateArea() {
    return  0.5 * (a.getX() * b.getY() - c.getY())
    + (b.getX() * c.getY() - a.getY())
    + (c.getX() * a.getY() - b.getY());
    }
    }


Und in der main dann so:
Code:
    package geo;
     
    public class TestGeo {
     
    public static void main(String[] args) {
     
    Punkt p1 = new Punkt(0,10);
    Punkt p2 = new Punkt(5,5);
    Punkt p3 = new Punkt(10,5);
    Punkt p4 = new Punkt(15,10);
    Punkt p5 = new Punkt(20,0);
    Punkt p6 = new Punkt(-5,5);
    Punkt p7 = new Punkt(-15,5);
    Punkt p8 = new Punkt(-15,-5);
    Punkt p9 = new Punkt(0,-5);
     
    Dreieck d1 = new Dreieck(p1, p2, p3);
    double z = d1.calcualteArea();
     
    Dreieck d2 = new Dreieck(p3, p4, p5);
    double v = d2.calcualteArea();
    Dreieck d3 = new Dreieck(p7, p8, p9);
    double o = d3.calcualteArea();
    if ((z < 0)|(v < 0)|(o < 0)) {
     
    System.out.println("Die Fläche ist < 0 --> ungültige Eingabe");
    } else {
     
    System.out.println("Die Fläche von D1 ist " + z);
    System.out.println("Die Fläche von D2 ist " + v);
    System.out.println("Die Fläche von D3 ist " + o);
     
    }
     
    }

du brauchst nicht für jedes mal fläche berechnen eine neue methode :)
 
Zurück
Oben