ich habe bisher in keinem Tut gefunden, was genau der Vorteil/Nutzen von einer abstrakten Klasse sein soll. Wenn ich den Teil Vererbung richtig verstanden habe, erben sub-klassen von den super-klassen, egal ob abstrakt oder nicht.
Reggie
Ja, aber mit dem Schlüsselwort abstract ist eben klar dass diese Klasse nicht zum Instanziieren gedacht warich habe bisher in keinem Tut gefunden, was genau der Vorteil/Nutzen von einer abstrakten Klasse sein soll. Wenn ich den Teil Vererbung richtig verstanden habe, erben sub-klassen von den super-klassen, egal ob abstrakt oder nicht.
public abstract class Tier {
// irgendwas, was Tiere gemeinsam haben
}
public class Hund extends Tier {
}
ist doch das selbe wie:Stell Dir vor, Du hast folgende Klasse:
Und warum ist die Klasse Tier nun abstract? Ganz einfach: stell Dir einfach die Frage, wie ein Tier aussieht. Ist es groß, klein, braun, lila usw. - schwierig. Im Gegensatz dazu ist ein Hund ein "greifbares" Objekt. Den kann man per Instanzvariablen so "beschreiben", dass es hinterher auch ein Hund ist und nicht eine bellend schwimmende Katze oder so.Java:public abstract class Tier { // irgendwas, was Tiere gemeinsam haben } public class Hund extends Tier { }
public class Tier {
// Oberklasse
}
public class Hund extends Tier {
// Unterklasse
}
Die Frage ist falsch herum gestellt: Was kann ich mit abstrakten Klassen nicht tun was ich mit konkreten Klassen kann? ;-)vielleicht sollte ich die Frage umformulieren:
Was kann ich mit abstrakten Klassen tun, was ich mit normalen Ober- und Unterklassen nicht kann?
Nein.Ist Dir denn der Sinn und Zweck von Interfaces bekannt? Das wäre eine Voraussetzung für das Verständnis von abstrakten Klassen.
und
ist doch das selbe wie:Stell Dir vor, Du hast folgende Klasse:
Java:public abstract class Tier { // irgendwas, was Tiere gemeinsam haben } public class Hund extends Tier { }
Java:public class Tier { // Oberklasse } public class Hund extends Tier { // Unterklasse }
public abstract class Tier {
public abstract int getNumberOfLegs();
// noch mehr
}
public class Hund extends Tier {
public int getNumberOfLegs() {
return 4;
}
// auch noch mehr
}
ohne abstract sollte es doch genauso gehen, oder? wenn nicht, dann bitte erklärt es mir. ich will wirklich lernen.Was machst du jetzt?Java:public class Tier { public int getNumberOfLegs(); // noch mehr } public class Hund extends Tier { public int getNumberOfLegs() { return 4; } // auch noch mehr }
interface Tier {
void friß();
void gibLaut();
}
class AbstraktesTier implements Tier {
public void friß() {
System.out.println("Nom, nom, nom..."); // Ist bei allen Tieren gleich
}
public abstract void gibLaut(); // Ist nach wie vor abstract
}
class Hund extends AbstraktesTier implements Tier {
public void gibLaut() {
System.out.println("Wuff");
}
}
class Katze extends AbstraktesTier implements Tier {
public void gibLaut() {
System.out.println("Muuuhhhh");
}
}
Nein, denn durch die abstrakte Methode gibLaut() - schau mal genau hin - da ist ein Semikolon hinter der Methode und keine geschweiften Klammern, muss die Klasse abstract sein. Und abstrakte Methoden bedeuten, dass die Erben der Klasse diese Methoden implementieren müssen. In unserem Fall müssen also alle konkreten Tiere diese Methode implementieren.ohne abstract sollte es doch genauso gehen, oder? wenn nicht, dann bitte erklärt es mir. ich will wirklich lernen.
Reggie
Man braucht keine abstrakten Klassen. Und manche Leute postulieren sogar, dass es keinen Grund gibt, sie zu benutzen. Man kann mit Interfaces+NormalenKlassen alles machen, was man auch mit abtrakten Klassen machen kann. Die Begründung, DOCH abstrakte Klassen zu verwenden, ist, lapidar formuliert: Sie sparen Arbeit. Am schon angedeuteten Beispiel:
[...]
Die Methode "friß()" ist bei allen Tieren gleich, und kann deswegen in der abstrakten Klasse stehen. Man KÖNNTE die abstrakte Klasse auch weglassen, und stattdessen die Methode (zwei mal gleich!) in den konkreten Klassen implementieren.
Das ist etwas vereinfacht, aber darauf läuft's meistens raus. Trotzdem sollte man sich überlegen, wie und wo man Abstrakte Klassen verwendet. Sie können die Strukturen ein bißchen "unschöner" machen. Ein bißchen was steht dazu auch in Practical API Design: Confessions of ... - Google Books
public abstract class AbstraktesTier {
public void friß() {
System.out.println("Nom, nom, nom..."); // Ist bei allen Tieren gleich
}
public abstract void gibLaut(); // Ist nach wie vor abstract
}
public class Hund extends AbstraktesTier {
public void gibLaut() {
System.out.println("Wuff");
}
}
public class Katze extends AbstraktesTier {
public void gibLaut() {
System.out.println("Muuuhhhh");
}
}
Architektonisch sind Interfaces und abstrakte Klassen das selbe, nämlich Schnittstellen. Ich finde es ad absurdum, wenn man für eine abstrakte klasse noch extrig ein Interface macht.
public class Tier {
public int getNumberOfLegs();
// noch mehr
}
public class Hund extends Tier {
public int getNumberOfLegs() {
return 4;
}
// auch noch mehr
}
Was machst du jetzt?
ohne abstract sollte es doch genauso gehen, oder? wenn nicht, dann bitte erklärt es mir. ich will wirklich lernen.
Reggie
Nein.
aber so wie ich das sehe brauche ich keine abstrakten Klassen.... zumindest bis ich mehr drauf habe
Reggie
Architektonisch sind Interfaces und abstrakte Klassen das selbe, nämlich Schnittstellen. Ich finde es ad absurdum, wenn man für eine abstrakte klasse noch extrig ein Interface macht.
class AbstraktesTier {
public void friß() { ... }
public abstract void gibLaut();
public void legDichInsKörbchen() { ... }
}
class Katze extends AbstraktesTier implements Tier {
public void gibLaut() {
System.out.println("Muuuhhhh");
}
Java:public abstract class Tier { public abstract int getNumberOfLegs(); // noch mehr } public class Hund extends Tier { public int getNumberOfLegs() { return 4; } // auch noch mehr }
ohne abstract sollte es doch genauso gehen, oder? wenn nicht, dann bitte erklärt es mir. ich will wirklich lernen.
Reggie
wenn es um die Anzahl der Beine von der Oberklasse (oder halt abstract) "Tier" geht würde ich in der Tier-Klasse eine public static final int numberOfLegs = 4; eintragen. sollte man allerdings Tier-Unterklassen erstellen wollen mit Beine != 4, dann würde ich eine Konstante in jeder der Unterklassen definieren.Und wie bitte schön, willst du dann die Anzahl der Beine von Tier bestimmen ? Wie viele Beine hat deiner Meinung nach ein Tier ? Also für mich hängt das irgendwie von dem ab, was für ein Tier es ist. Und wieso soll deiner Meinung nach ein Tier instanziert werden können ? Hast du schon mal gesehen, dass ein Tier geboren wurde ? (also ein Tier, das weder ein Hund, noch ein anderes Tier ist, also keine Gattung hat und unbekannte Anzahl an beinen etc....) Also ich glaube auch wenn ich nichts mit Programmieren zu tun hätte, würde ich es nach all den deutlichen Erklärungen hier verstehen. Ich weiß nicht wirklich was dein Problem ist...
Sie sind nicht 100% gleichwertig, der Unterschied machts, abstrakte Klassen die Schnittstellen implementieren sind üblich und oft vorteilhaft, siehe zB. das Collection Framework, Bloch hat das ganz gut in Effective Java beschrieben.Architektonisch sind Interfaces und abstrakte Klassen das selbe, nämlich Schnittstellen. Ich finde es ad absurdum, wenn man für eine abstrakte klasse noch extrig ein Interface macht.
ja, eine gute Erklärung. dankeDu schreibst ne Klasse, die aber an sich nicht funktionieren wird, sondern von anderen Klassen (also von den Klassen, die die Benutzer schreiben) abgeleitet werden muss. In diesem Fall willst du verhindern, dass solche Klasse, ohne Ableitung Instanziert werden kann. Und das kannst du ja mit einer abstrakten Klasse realisieren. Außerdem, wird ja deine Klasse Methoden beinhalten, die Teilweise von dir implementiert sind, aber auch solche, die von der Konkreten Implementierung des Benutzers abhängen (also je nach seinen Anforderungen). Solch eine Klasse kann nicht ohne Ableitung Instanziert werden, und genau das ist ja dein Vorhaben.
[...]
Ist das jetzt vlt. klarer geworden ?
wenn man das auch nie vorhatte, macht es also keinen Unterschied, ob man eine abstrakte klasse benutzt.
public interface Module {
void configure(Binder binder);
}
public class MyModule implements Module {
@Override
public void configure(Binder binder) {
binder.bind(Foo.class).to(FooImpl.class);
binder.bindProvider(SomeProvider.class);
// ... whatever
}
}
public abstract class AbstractModule implements Module {
private Binder binder;
@Override
public final void configure(Binder binder) {
try {
this.binder = binder;
configure();
} finally {
binder = null;
}
}
protected abstract void configure();
protected BindBuilder bind(Class<?> clazz) {
return binder.bind(clazz);
}
protected void bindProvider(Class<? extends Provider> providerClass) {
binder.bindProvider(providerClass);
}
}
public class MyModule extends AbstractModule {
@Override
public void configure() {
bind(Foo.class).to(FooImpl.class);
bindProvider(SomeProvider.class);
// ... whatever
}
}
public interface Tier {
public String gibLaut();
}
public class AbstractTier implements Tier{
private String name;
private double gewicht;
public double getGewicht(){
return gewicht;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public void setGewicht(double gewicht){
this.gewicht = gewicht;
}
@Override
public String gibLaut() {
return null;
}
}
public class Hund extends AbstractTier{
String rasse;
public Hund(String name, double gewicht){
super();
setName(name);
setGewicht(gewicht);
}
public void setRasse(String rasse){
this.rasse=rasse;
}
}
public abstract class AbstractTier implements Tier{
private String name;
private double gewicht;
public double getGewicht(){
return gewicht;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public void setGewicht(double gewicht){
this.gewicht = gewicht;
}
}
public class Hund extends AbstractTier{
String rasse;
public Hund(String name, double gewicht){
super();
setName(name);
setGewicht(gewicht);
}
public void setRasse(String rasse){
this.rasse=rasse;
}
@Override
public String gibLaut() {
return "woof";
}
}
statt mich zu fragen, wie ich das Beispielproblem sonst lösen wollte, würde ich mir lieber ein Beispiel wünschen, dass NUR mit abstract funktioniert UND erklärt, warum es ohne abstract nicht funktionieren würde.
interface Tier
{
void friß(); // Diese Methoden sind immer 'public'
void gibLaut(); // (auch wenn kein 'public' davor steht!)
}
abstract class AbstraktesTier implements Tier
{
protected void verdaueFutter()
{
// Diese Methode erfüllt eine Funktion, die "oft" gebraucht wird,
// wenn man ein konkretes Tier implementieren will. Allerdings
// ist die Methode 'protected', d.h. sie sollte NUR von Klassen
// aufgerufen werden, die von "AbstraktesTier" erben - und
// nicht von irgendwelchen anderen Klassen!
}
// Diese Methoden sind immernoch abstrakt:
//public abstract void friß();
//public abstract void gibLaut();
}
class Hund extends AbstraktesTier implements Tier
{
public void friß()
{
System.out.println("Nom, nom, nom");
verdaueFutter(); // Ruft die 'protected'-Methode aus AbstraktesTier auf
}
public void gibLaut()
{
System.out.println("Wuff");
}
}
will mitstreiten
Vererbung ist eins der meistgehypten und meist missverstandenen/missbrauchten feature seit erfindung von Programmieren... lieber weglassen und nur nehmen wenns ueberhaupt nicht geht.
Die "alte" Frage von IS-A ist meiner ansicht nach so und so falsch.. nur bei "Behaves-like" kann man es in betracht ziehen.
Ansonsten immer beachten: Komposition >>>>> Vererbung.
-----
und nu schoen alle erzaehlen warum Vererbung doch gut ist bzw wie ich sachen denn ohne Vererbung machen will...