QuoteEin Perl-Objekt ist eine Referenz die weiß zu welcher Klasse sie gehört.
2017-07-12T06:14:10 rostiDas ist ein ziemlicher Unsinn der da verbreitet wird: Objekte senden Messages an Objekte -- So ein Stuss!
Objekte sind Instanzen von Klassen, nicht nur in Perl!
Und dann schauen wir doch mal in ein gutes Buch, wie z.B. Eric Foster Johnson definiert, was ein Objekt ist:
QuoteEin Perl-Objekt ist eine Referenz die weiß zu welcher Klasse sie gehört.
In dieser Konsequenz kann ein Objekt gar keine Methoden anderer Klassen aufrufen, jeglicher Datenfluss spielt sich immer nur innerhalb einer Klasse ab!
$getraenkeautomat->gibMirEineCola();
Quotemessages cannot pass object references
QuoteI've never seen a Java or C# code-base, that follows that rule.
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
#!/usr/bin/perl use warnings; use strict; package Getraenkeautomat; sub new { my $classname = shift; my $self = {bottles_of_cola => 10}; return bless($self, $classname); } sub gibMirEineCola { my $self = shift; if ($self->{bottles_of_cola} > 0) { print "Bitteschoen!\n"; $self->{bottles_of_cola}--; print "Noch $self->{bottles_of_cola} Flaschen Cola uebrig.\n"; } } package Man; sub new { my $classname = shift; my $self = {thirst => 0}; return bless($self, $classname); } sub sweat { my $self = shift; my $getraenkeautomat = shift; print "Ganz schoene Hitze, ich werde durstiger.\n"; $self->{thirst}++; if ($self->{thirst} > 1) { print "Ich brauche eine Cola!\n"; $getraenkeautomat->gibMirEineCola(); } } package main; my $getraenkeautomat = Getraenkeautomat->new(); my $user = Man->new(); $user->sweat($getraenkeautomat); $user->sweat($getraenkeautomat);
$user->sweat($getraenkeautomat);
2017-07-12T17:31:44 rostiUnd das ist eben das was man besser nicht machen sollte. Wie man es besser macht, habe ich aber auch erklärt. Stichwort factory, delegation.
1 2 3 4 5 6 7 8 9 10 11
package Man; # aggregation sub new { my $classname = shift; my $self = { thirst => 0, COLABOT => Getraenkeautomat->new }; return bless($self, $classname); }
1 2 3 4 5 6 7 8 9
package Man; # delegation # die Methode einer nicht verwandten Klasse wird zu einer # eigenen Methode gemacht sub gibMirEineCola{ my $self = shift; return $self->{COLABOT}->gibMirEineCola(@_); }
2017-07-13T08:59:41 rostiCode (perl): (dl )1 2 3 4 5 6 7 8 9 10 11package Man; # aggregation sub new { my $classname = shift; my $self = { thirst => 0, COLABOT => Getraenkeautomat->new }; return bless($self, $classname); }
und delegiere gibMirEineCola als eine eigene Methode:
Code (perl): (dl )1 2 3 4 5 6 7 8 9package Man; # delegation # die Methode einer nicht verwandten Klasse wird zu einer # eigenen Methode gemacht sub gibMirEineCola{ my $self = shift; return $self->{COLABOT}->gibMirEineCola(@_); }
Später delegieren geht natürlich auch, siehe factory. Fehlersuche und Debuggen wird erleichtert, ein Dump auf das $user-Objekt genügt um auch die Eigenschaften des COLABOT zu zeigen. MfG
2017-07-12T20:18:27 rostiGuck Dir mein Framework an, da stecken 15 Jahre OOP Erfahrung drin, Codebeispiele inklusive.
MfG
2017-07-17T07:57:02 reneeDas sind immer Zusammenhanglose Beispiele. Was hat das groß mit OOP zu tun? Für dieses Package brauchst Du 15 Jahre Erfahrung OOP?
2017-07-17T08:34:04 rostiDie ganze Idee zur Reife zu bringen ist natürlich ein etwas längerer Prozess. Ohne OOP jedoch undenkbar.
... das ist alles in Subklassen organisiert und außerhalb vom CODE konfigurierbar.
1 2
# $self ist die FW Instanz $old_title = $self->eav('title', 'Neuer Titel für die Response');
2017-07-13T06:24:49 MuffiRein interessehalber:
Was wäre jetzt der Vorschlag ohne OO?
MuffiUnd wenn einem der Vorschlag hier zu verwurschtelt wird, dann spricht auch in OO nichts dagegen eine "Bank" einzuführen, die den Handel übernimmt.
2017-07-12T06:14:10 rostiEs geht alles ;-)In dieser Konsequenz kann ein Objekt gar keine Methoden anderer Klassen aufrufen,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
use v5.10; package A { sub new { return bless {}, shift; } sub test { say __PACKAGE__ } } package B { sub new { return bless {}, shift; } sub test { say __PACKAGE__ } } my $a = A->new; $a->B::test(); $a->test;
2017-07-12T06:14:10 rostiWenn ein klassenübergreifender Datenaustausch stattfinden soll gibt es einmal die Möglichkeit der Vererbung: vererbt werden Eigenschaften und Methoden und siehe da, hier können selbstverständlich auch Daten fließen, siehe oben. Perl bietet überdies auch die Möglichkeit der Mehrfachvererbung.
2017-07-12T06:14:10 rostiVorsicht vor zirkulären Referenzen!Man sollte jedoch eine Klasse sehr genau kennen, bevor man deren Erbe antritt. Von daher bietet sich als zweite Möglichkeit für einen klassenübergreifenden Datenaustausch die Delegierung an, Beispiel:
Und somit wird die eigene Instanz befähigt, Methoden der anderen Klasse aufzurufen. Das CGI-Objekt und dessen Eigenschaften sowie Referenzen beleiben jedoch strict getrennt von den anderen Eigenschaften der eigenen Klasseninstanz.
package EineKlasse;
package main;
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
#!/usr/bin/perl use warnings; use strict; package Getraenkeautomat { sub new { my $classname = shift; my $self = {bottles_of_cola => 10}; return bless($self, $classname); } sub gibMirEineCola { my $self = shift; if ($self->{bottles_of_cola} > 0) { print "Bitteschoen!\n"; $self->{bottles_of_cola}--; print "Noch $self->{bottles_of_cola} Flaschen Cola uebrig.\n"; } } } package Man { sub new { my $classname = shift; my $self = {thirst => 0}; return bless($self, $classname); } sub sweat { my $self = shift; my $getraenkeautomat = shift; print "Ganz schoene Hitze, ich werde durstiger.\n"; $self->{thirst}++; if ($self->{thirst} > 1) { print "Ich brauche eine Cola!\n"; $getraenkeautomat->gibMirEineCola(); } } } my $getraenkeautomat = Getraenkeautomat->new(); my $user = Man->new(); $user->sweat($getraenkeautomat); $user->sweat($getraenkeautomat);
2017-07-13T10:13:11 GwenDragonNein, das geht nicht, es ist ein Schlüsselwort in Perl.
1 2 3 4 5 6 7 8 9
# classToPackage.pm package classToPackage; use Filter::Simple; FILTER { s/class /package /g; }; 1;
2017-07-14T22:44:12 betterworldHat es übrigens einen Grund, dass ein Timestamp in deinem Video-Link drin war?
2017-07-14T22:44:12 betterworldAlso dass er von 1000 Zeilen langen Funktionen schwärmt und sich Sprachen wünscht, die es ihm noch leichter zu machen, so lange Funktionen zu schreiben und darin auch noch Unterfunktionen zu definieren...
1 2 3 4 5 6 7 8 9 10 11
#include <stdio.h> int main() { int subFunc() { return 5; } printf("%d\n", subFunc()); return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13
#!/usr/bin/perl use warnings; use strict; sub func1 { sub func2 { return 5; } print func2() . "\n"; } func1();
2017-07-14T23:49:18 hlubenowIn kleine Funktionen zu teilen, macht jedenfalls Sinn, wenn sie mehrfach aufgerufen werden.
QuoteFunktionen in Funktionen gibt es z.B. in Pascal. [... ] In Perl geht's auch
2017-07-15T07:20:26 betterworldHier sind foo und main ganz normale Funktionen (Subroutinen), und foo kann die Variable $x nicht sehen. Genau das will er haben, bloß dass er die Definition von foo in main drinne haben will und immer noch nicht $x sehen können will.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
program NestedProcedures (output); procedure main(); procedure foo(); begin writeln('hello'); { This would fail here: writeln(x); } end; var x : integer; begin x := 2; foo(); end; begin main(); end.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
#!/usr/bin/perl use v5.22; use strict; use warnings; use experimental 'lexical_subs'; no warnings 'experimental::lexical_subs'; foo(); bar(1); sub foo { say 'foo'; my sub bar { say "bar " . shift; } bar(2); }
Quote$ perl private_sub.pl
foo
bar 2
Undefined subroutine &main::bar called at private_sub.pl line 12.
Guest werObjektA kennt ein ObjectB aber ObjectC kennt auch ObjectB. Wenn nun ObjektA ObjectB Daten übergibt, so muss verhindert werden das ObjectC im selben Augenblick Daten abfragt, die Daten Sind ja unter Umständen veraltet oder in einem ungültigen Zustand. Alle Verbindungen zu ObjektB bis auf die zu ObjektA müssen gesperrt sein solange die Daten Transferiert werden.
Das ist alles kein Problem wenn ein Prozess alle Objekte verwaltet. Da immer nur ein Objekt handeln kann. Kein anderes kann jemals ungültige/veraltete Daten lesen.
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
# erstelle gleich mal 2 Instanzen # Fahrzeugführer ID wird durchgereicht $pkw = Auto->new(ffid => 1); $suv = Auto->new(ffid => 2); # Wenn der Fahrer gescheckt werden soll, ruft die Auto-Instanz eine eigene Methode $pkw->check; $suv->check; # Anwendungsklasse package Auto; # Argumente für die Konstruktoren nicht verwandter Klassen werden durchgereicht # für Debugzwecke wird die gesamte Konfiguration in der eigenen Instanz mitgeschleift sub new{ my $class = shift; my %cfg = ( ffid => '', # Fahrzeugführer ID # ggf. weitere Defaults @_); my $self = bless{ Fahrer => Fahrer->new( $cfg{ffid} ), Polizist => Polizei->new, CFG => \%cfg, ), $class; } # Delegation in eine eigene Methode # mit eigener Fehlerbehandlung sub check{ my $self = shift; my $fuehrerschein = $self->{Fahrer}->fuehrerschein(); $self->{Polizist}->check( $fuehrerschein) || $self->fehlerbehandlung(); }