Objektorientierte Programmierung in der Schule





  • Vielleicht sollte ich schreiben, dass das Java Code ist !



  • Wozu, das sieht man doch. Auch in Java gelten grundlegende OO-Prinzipien 🙂



  • Erfüllt eine Funktion die einen Pointer oder eine Referenz auf eine Basisklasse erwartet eine bestimmte Aufgabe, so muss diese Funktion die selbe Aufgabe auch mit einem Objekt einer abgeleiteten Klasse erfüllen können.

    Tut mein Code das nicht ? Also ich sehe die Verletzung des Prinzip nicht!



  • Dann schau doch bitte hin.



  • Bei dir gilt schon die IST-EIN-Beziehung nicht. Ein Rechteck ist eben im Allgemeinen kein Quadrat. Wenn du also eine Methode hast, die mit Quadraten arbeitet und von typischen Quadrat-Eigenschaften ausgeht (z.B. dass es 4 Seiten hat, die alle gleich lang sind), wird sie kolossal durcheinanderkommen, wenn du ihr ein Rechteck oder gar einen Quader unterschiebst. Deine Vererbung lässt also keine Polymorphie zu.



  • Dann frage ich mich Warum das hier klappt?

    class Quadrat{
    	int a;
    
    	Quadrat(int a){
    		this.a = a;
    	}
    
    	int flache(){
    		return a*a;
    	}
    }
    
    class Wuerfel extends Quadrat{
    	Wuerfel(int a){
    		super(a);
    	}
    
    	int flache(){
    		return 6*a*a;
    	}
    }
    
    class Rechteck extends Quadrat{
    	int b;
    
    	Rechteck(int a, int b){
    		super(a);
    		this.b = b;
    	}
    
    	int flache(){
    		return a*b;
    	}
    }
    
    class Quader extends Rechteck{
    	int c;
    
    	Quader(int a, int b, int c){
    		super(a, b);
    		this.c = c;
    	}
    
    	int flache(){
    		return 2*a*b+2*a*c+2*b*c;
    	}
    
    }
    
    public class vererbung {
    	public static int summe(Quadrat[] q){
    		int sum = 0;
    		for(int i = 0; i < q.length; ++i)
    		{
    			sum += q[i].flache();
    		}
    
    		return sum; 
    	}
    
    	public static void main(String[] args) {
    		Quadrat[] q = new Quadrat[4];
    
    		q[0] = new Quadrat(2);
    		q[1] = new Wuerfel(2);
    		q[2] = new Rechteck(2,3);
    		q[3] = new Quader(2,3,4);
    
    		System.out.println(q[0].flache());
    		System.out.println(q[1].flache());
    		System.out.println(q[2].flache());
    		System.out.println(q[3].flache());
    		System.out.println(summe(q));
    	}
    }
    


  • Weil deine Funktion nicht davon ausgeht ein Quadrat zu bekommen, sondern lediglich ein Ding, was eine Fläche hat. Eine dem angemessene Vererbungsstruktur dafür wär also, dass Quadrat, Rechteck etc. von der abstrakten Klasse/Interface Flaeche abgeleitet sind oder so.
    Es sagt ja keiner, dass deine Struktur nie funktioniert. Nur dass sie etwas kommuniziert, was sie nicht leisten kann, und daher schlechter OO-Stil ist.



  • Also ich sehe nicht die Verletzung des Prinzip !

    Das kommt auf die Verträge an, die du für deine Methoden festlegst. Wenn du überhaupt nichts garantierst, dann kannst du auch alles von allem ableiten ohne das Prinzip zu verletzen (eine Funktion die eine Basisklassenreferenz erhält bekommt keinerlei Garantien, also kann auch nichts verletzt werden).
    Nur gewinnst du dann nichts:

    class Banana
    {
    public:
        virtual void turn_yellow() {...}
        virtual void chop() {...}
        virtual void peel() {...}
    };
    
    // a monkey is a special case of banana except it doesn't peel, turn_yellow 
    // or chop. It does jump, squeal, swing_from_trees though.
    class Monkey : public Banana
    {
    public:
        // Basisklassenmethoden zu NOPs machen...
        virtual void turn_yellow() {}
        virtual void chop() {}
        virtual void peel() {}
    
       // ...und neue Methoden hinzufügen
        virtual void jump() {...}
        virtual void squeal() {...}
        virtual void swing_from_tree() {...}
    
    };
    

    Wenn du, wie in deinem Fall, nur eine Methode hast und nichts weiter garantierst, als dass diese Methode den Flächeninhalt des Objekts liefert, dann ist das auch ok. Sobald deine Klasse aber wirklich sinnvolles Verhalten hat, bekommst du Probleme.

    Quadrat ist kein Rechteck und Rechteck kein Quadrat. Beides sind Spezialisierung von Shape:

    class Shape 
    {
    public:
        virtual int flaeche() = 0;
    };
    
    class Quadrat : public Shape
    {
    ...
    };
    
    class Rechteck : public Shape
    {
    ...
    };
    


  • Warum sollte es nicht funktionieren?
    Was beweist das?

    Folgendes geht zB nicht:

    void quadriereFlaeche(Quadrat const& q)
    {
      q.setSize(q.getSize()*2);
    }
    

    Daran wird n Rechteck scheitern...
    Oder wie willst du setSize() implementieren?



  • Einsicht ist gekommen - jetzt weiss ich was ihr meint !


Anmelden zum Antworten