Leere Oberklasse sinnvoll?

Neue Frage »

Auf diesen Beitrag antworten »
Haevelin Leere Oberklasse sinnvoll?

Wenn ich eine Klasse Rechteck und eine Klasse Kreis habe, und ich möchte die Objekte, die ich hiervon erstelle in eine ArrayList in Java speichern, so bin ich so vorgegangen, dass ich eine leere Klasse Figur kreiiert habe, Rechteck und Kreis davon erben lasse, und in die ArrayList<Figur> figur alle Elemente von Rechteck und Kreis geschrieben habe. Später dann die Abfrage mit bspw. figur instanceof Rechteck durchführen, um zu entscheiden, was mit der konkreten Figur weiter zu geschehen hat.
Das Figur dabei eine leere Klasse ist, scheint nicht zu stören? Es hat also Sinn leere Klasse als Superklasse zu definieren!
public class Figur {
}

public class Rechteck extends Figur {
double seiteA, seiteB;
....
}

Was ist von diesen Ideen zu halten?
 
Auf diesen Beitrag antworten »
as_string RE: Leere Oberklasse sinnvoll?

Zitat:
Original von Haevelin
Später dann die Abfrage mit bspw. figur instanceof Rechteck durchführen, um zu entscheiden, was mit der konkreten Figur weiter zu geschehen hat.

Das solltest Du nach Möglichkeit nicht machen! Wenn Du eine Methode von einer dieser Figuren aufrufst, dann wird eine gleichnamige Methode in der konkreten Unterklasse aufgerufen werden. So unterschiedest Du, nicht durch ein "instanceof" (Ausnahmen bestätigen die Regel...). So was nennt man dann auch Polymorphy.
Die Idee ist: wenn Du z. B. eine Methode "zeichne()" hast, dann soll das Rechteck wissen, wie das geht für ein Rechteck, und ein Kreis für einen Kreis, mit den jeweiligen Daten, die ein Rechteck oder ein Kreis hat. Deshalb soll es genau darin definiert sein und Du sollst sagen können: "Hier habe ich eine Liste von Figuren, die entweder Kreise oder Rechtecke sein können. Ich will die alle zeichnen, also sag ich denen allen, weil die es wissen, was sie tun müssen!" Das "instanceof" macht Java dann quasi automatisch!

Zitat:
Original von Haevelin
Das Figur dabei eine leere Klasse ist, scheint nicht zu stören? Es hat also Sinn leere Klasse als Superklasse zu definieren!
public class Figur {
}

public class Rechteck extends Figur {
double seiteA, seiteB;
....
}

Was ist von diesen Ideen zu halten?

Ja, das macht man dann allerdings als sogenannte "abstract" Oberklasse. Dann schreibst Du rein, welche Funktionen es geben muss für alle Klassen die diese beerben, ohne einen Funktionsblock wirklich schreiben zu müssen, weil es nur abstrakt deklariert ist. Dafür kannst Du dann nur Objekte von den abgeleiteten Klassen instanziieren, aber nicht von der abstrakten. Aber das ist ja auch sinnvoll, oder?

In Java wäre noch zu überlegen, ob Du es nicht vielleicht als Interface deklarierst.

Gruß
Marco
Auf diesen Beitrag antworten »
Haevelin RE: Leere Oberklasse sinnvoll?

Besser, wenn ich meinen funktionierenden Code einmal angebe:

1) Die Klasse Objekt

public class Objekt {

}

2) Die erbenden Klassen Rechteck und Kreis

public class Rechteck extends Objekt {
private double seitenlaenge;

public Rechteck(double laenge) {
this.seitenlaenge = laenge;
}

public double flaeche() {
return seitenlaenge * seitenlaenge;
}
}



public class Kreis extends Objekt {
private double radius;

public Kreis(double radius) {
this.radius = radius;
}

public double flaeche() {
return radius * 2 * Math.PI;
}

}


3) Die Testklasse

import java.util.ArrayList;

public class TestObjekt {

public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<Objekt> liste = new ArrayList<Objekt>();
Rechteck r1 = new Rechteck(2.0);
liste.add(r1);
Rechteck r2 = new Rechteck(3.0);
liste.add(r2);
Kreis k1 = new Kreis(2.0);
liste.add(k1);
Kreis k2 = new Kreis(3.0);
liste.add(k2);
for (Objekt k : liste) {
if (k instanceof Rechteck) {
System.out.println(((Rechteck) k).flaeche());

}
if (k instanceof Kreis) {
System.out.println(((Kreis) k).flaeche());
}
}
}

}
Auf diesen Beitrag antworten »
as_string

Ich kann leider erst drüber schauen, wenn ich zu Hause bin... Ich melde mich dann heute Abend.
Aber schau mal im Internet nach "java abstract super class" oder ähnliches. Da solltest Du vieles Interessantes dazu finden können!

Gruß
Marco
 
Auf diesen Beitrag antworten »
as_string

Hallo!

Nein, das macht man etwas anders. Die Oberklasse ist nicht wirklich komplett leer, sondern definiert den Umfang an Methoden, die Du auf jeden Fall von jeder abgeleiteten Klasse erwartest, egal welche konkrete Ausprägung sie darstellt.

Du möchtest in Deinem Beispiel ja offenbar, dass beide Unterklassen einen Flächeninhalt ausgeben können. Das ist also eine Methode, die ein "Ding" von der Art "Figur" auf jeden Fall unterstützen muss (jetzt hast Du das "Objekt" genannt, aber das finde ich gar nicht gut, weil es in Java schon ein "Object" gibt, von dem automatisch jede Klasse erbt und Dein "Objekt" vom Namen her dann ja auch nichts aussagt. Bleiben wir lieber bei "Figur"!).

Weil Du aber in der Oberklasse diese Funktion noch gar nicht ausimplementieren kannst, machst Du eine abstrakte Oberklasse namens Figur, etwa so:
code:
1:
2:
3:
public abstract class Figur {
	public abstract double flaeche();
}


Dann sehen die zwei abgeleiteten Klassen so aus (ich habe die eine nicht Rechteck, sondern Quadrat genannt, da ja offenbar jede Seite die selbe Länge haben soll...)
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
public final class Quadrat extends Figur {
	private double seitenlaenge = 0.0;

	public Quadrat(double seitenlaenge) {
		super();
		this.seitenlaenge = seitenlaenge;
	}

	@Override
	public double flaeche() {
		return seitenlaenge * seitenlaenge;
	}

}


public final class Kreis extends Figur {
	private double radius = 0.0;

	public Kreis(double radius) {
		super();
		this.radius = radius;
	}

	@Override
	public double flaeche() {
		return Math.PI * radius * radius;
	}

}

Übrigens ist die Kreisfläche immer noch pi*r^2 und nicht 2pi * r, was der Umfang wäre!
Ich habe bei mir jetzt immer noch den super()-Konstruktor aufgerufen. Das kannst Du natürlich weg lassen in diesem Fall, weil die Super-Klasse gar keinen Konstruktor hat (bis jetzt...).

Dann kannst Du nämlich ganz ohne das instanceof if/switch-Verhauen und cast-Orgien leben:
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
import java.util.ArrayList;

public class polymorphy_test {

	public static void main(String[] args) {
		ArrayList<Figur> liste = new ArrayList<>();
		Quadrat r1 = new Quadrat(2.0);
		liste.add(r1);
		Quadrat r2 = new Quadrat(3.0);
		liste.add(r2);
		Kreis k1 = new Kreis(2.0);
		liste.add(k1);
		Kreis k2 = new Kreis(3.0);
		liste.add(k2);
		for (Figur k : liste) {
			System.out.println(k.flaeche());
		}
	}

}


Ich habe wieder etwas umbenannt... Aber siehst Du wie einfach plötzlich die for-Schleife wird?
Noch viel, viel wichtiger ist aber: Normalerweise hast Du ja eine Liste von Figur-Objekten irgendwie generiert, vielleicht Daten aus einer Datei gelesen oder einen Benutzer eingeben lassen. Jetzt willst Du immer von der ganzen Liste die Flächen ausgeben, dann genügt diese kurze For-Schleife. Wenn Du irgendwann mal eine neue Figur machen willst, z. B. ein echtes Rechteck, das Länge und Breite hat, dann genügt es eine solche Klasse zu machen und von Figur erben zu lassen. Du musst dann nur Objekte diesen neuen Typs in das Array rein bringen und schon funktioniert Deine for-Schleife völlig ohne Änderung.

Mit Deiner Technik würde das nicht gehen. Wenn Du eine neue Klasse machst und die in Dein Array packen wolltest, müsstest Du auch in jeder for-Schleife, die alle Objekte bearbeiten will, immer ein "if(k instanceof blabla)..." rein schreiben.

Wenn Du objektorientiert programmierst und Du hast solche if/switch-Blöcke in Deinem Code, dann ist das normalerweise ein Zeichen für eine schlechte Vererbungshierarchie und schlechte Ausnutzung der Polymorphie!

Gruß
Marco

PS: In diesem Fall hätte ich unter Java eher ein Interface benutzt!
 
Neue Frage »
Antworten »


Verwandte Themen

Die Beliebtesten »
Die Größten »
Die Neuesten »