QuoteZu beachten ist hierbei, dass die Entscheidung jeweils abhängig vom konkreten Fall ist. Ist beispielsweise eine Manipulation der geometrischen Figur nach der Erzeugung nicht vorgesehen, so kann Kreis durchaus von Ellipse abgeleitet sein: Dass die Achsen unabhängig voneinander skaliert werden können, ist dann keine Eigenschaft der Klasse Ellipse, und somit muss sie auch keine Eigenschaft von Kreis sein, um Kreis zur Unterklasse von Ellipse zu machen.
1 2 3 4 5 6 7 8
sub scale { my $self = shift; my ($x,$y) = @_; return defined($y) ? Eclipse->new($x * $self->x, $y * $self->x) : Kreis->new($x * $self->x); }
1 2 3 4 5 6 7 8 9 10 11 12
sub scale { my $self = shift; my ($x,$y) = @_; if (defined $y) { bless $self, 'Eclipse'; $self->scale(@_); } else { $self->set_x($x * $self->x); } }
1 2
my $kreis = Rundling->new(r => $r); my $elly = Rundling->new(x => $x, y => $y);
2025-06-25T09:25:57 rostiMeinen Prinzipien flacher Klassenhierachien folgend würde ich weder Kreis von Ellipse noch Ellipse von Kreis ableiten, sondern alles in einer Klasse abfackeln ;)
2025-06-25T15:12:03 rostiDas hatten wir gerade: Wenn Ellipse eine Methode scale($x,$y) anbietet, dann muss auch etwas sinnvolles passieren, wenn man Kreis->new->scale($x,$y) betreibt. Auch die Rückgabewerte müssen kompatibel sein: Wenn scale in der Klasse Ellipse ein neues Objekt zurückgibt, dann muss das auch für Kreis so sein. Das gilt für alle Methoden der Klasse Ellipse.Des Weiteren beschreibt Liskov, daß ein Programm mit der Instanz der Basisklasse genauso funktionieren muss wie mit einer Instanz der Subklasse. Hier habe ich ein echtes Verständnisproblem:
1) Was heißt genauso funktionieren?
2025-06-me25T15:12:03 rostiDas läßt sich sinngemäß einfach anwenden: Die Subklasse muss alle Methoden der Basisklasse sinnvoll bedienen, auch wenn's Objekte der Basisklasse gar nicht gibt. Im Beispiel2) Was ist, wenn die Basisklasse gar nicht instantiierbar ist? (die Basisklasse ist ein abstrakte Klasse wie z.B. UNIVERSAL oder Tie::Hash)
2025-06-26T06:00:54 rostiZusätzliche Methoden der Unterklasse sind explizit erlaubt. Deine Interpretation von "genauso funktionieren" ist nicht die, die ich beschrieben habe. Im Wikipedia-Artikel steht:Zu 1) gäbe es jedoch Fälle, daß es die Methoden der Subklasse in der Basisklasse gar nicht gibt.
So kann ein Programm mit der Instanz der Basisklasse nicht genauso funktionieren wie dasselbe Programm mit der Subklasseninstanz.
QuoteEin Programm, das die Basisklasse verwendet, kann die zusätzlichen Methoden der Unterklasse gar nicht verwenden und strengere Objektsysteme als das von Perl verhindern das auch.Es besagt, dass ein Programm, das Objekte einer Basisklasse T verwendet, auch mit Objekten der davon abgeleiteten Klasse S korrekt funktionieren muss, ohne dabei das Programm zu verändern.
QuoteEin Programm, das die Basisklasse verwendet, kann die zusätzlichen Methoden der Unterklasse gar nicht verwenden und strengere Objektsysteme als das von Perl verhindern das auch.
WikipediaDann ließe sich nicht stets bedenkenlos ein Objekt vom Typ T durch ein Objekt vom Typ S ersetzen.
2025-06-26T22:43:56 hlubenowWikipediaDann ließe sich nicht stets bedenkenlos ein Objekt vom Typ T durch ein Objekt vom Typ S ersetzen.
Na und, dann eben nicht.
2025-06-27T07:02:17 rostiMethoden die in nur einer Subklasse gebraucht werden, haben in der Basisklasse nichts zu suchen.
1 2
my $tank = Tank->new( fuel => 100 ); # volltanken my $pkw = PKW->new( tank => $tank ); # ein Auto bauen
my $pkw = PKW->new( tank => Tank->new(fuel => 100) );
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
package Tank{ use strict; use warnings; # Tank bauen sub new{ my $class = shift; my %cfg = ( fuel => 0, @_); return bless \%cfg, $class; } # Tankinhal ändern sub fuel{ my $self = shift; my $fuel = shift; unless( defined $fuel ){ return $self->{fuel} } else{ $self->{fuel} = $fuel } } }; package PKW{ use strict; use warnings; # Auto bauen sub new{ my $class = shift; my %cfg = (tank => {}, @_); bless \%cfg, $class; } # Tankinhalt ändern, delegierte Methode sub fuel{ my $self = shift; return $self->{tank}->fuel(@_); } }; 1; ########################################################## package main; use strict; use warnings; my $tank = Tank->new( fuel => 100 ); my $pkw = PKW->new( tank => $tank ); my $zweitwagen = PKW->new( tank => $tank ); $zweitwagen->fuel(0); # Leerfahren print $pkw->fuel; # Tank leer
2025-06-29T19:50:43 hlubenowTja, deshalb kann ja mehr als nur ein Objekt von einer Klasse instantiiert werden. Wenn man zwei Autos hat, sollten die sich nicht nur einen Tank teilen müssen. Sondern PKW1 bekommt Tank1, und PKW2 bekommt Tank2.
Dann kann man die Tanks auch problemlos an ihre zugehörigen PKW übergeben.
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
package PKW{ use strict; use warnings; # Auto bauen sub new{ my $class = shift; bless{ tank => Tank->new( fuel => 100 ) }, $class; } # Tankinhalt ändern, delegierte Methode sub fuel{ my $self = shift; return $self->{tank}->fuel(@_); } }; 1; ########################################################## package main; use strict; use warnings; use Data::Dumper; my $pkw = PKW->new(); my $zweitwagen = PKW->new(); $zweitwagen->fuel(0); # Leerfahren print $pkw->fuel;