Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]8706[/thread]

Perl und OOP: Ein paar Anfänger-Fragen



<< >> 9 Einträge, 1 Seite
Gast Gast
 2007-01-31 22:41
#73897 #73897
Hallo,

ich habe in der letzten Zeit angefangen mit Perl zu programmieren und habe ein paar Fragen bzgl. OOP. Mit anderen Sprachen habe ich schon einige Zeit verbracht und ein auch ein Weilchen Erfahrung mit OOP, nur klappt es bei Perl nicht so ganz mit dem Verständnis.

Meine erste Frage ist recht banal: Sollen Package-Namen mit einem Großbuchstaben anfangen oder nicht? Dass beides geht, also Groß- und Kleinschreibung, ist klar; nur was ist "richtig"?

Zweitens: Wie baue ich eine Klasse am besten auf? Dazu habe ich zwei Möglichkeiten gefunden.

Erste Möglichkeit:
Code: (dl )
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
### Hauptprogramm ###

#!/usr/bin/perl

use strict;

use lib './classes';
use builder;

my $builder;
$builder = builder->new("Author");
$builder->print();



### Package ###

package builder;

use strict;

sub new {
   my ($class, $author) = @_;

   my $self = { _author => $author };

   return bless($self, $class);
}

sub print {
   my ($self) = @_;

   print $self->{_author}."\n";
}

1;


Zweite Methode:
Code: (dl )
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
### Hauptprogramm ###

#!/usr/bin/perl

use strict;

use lib './classes';
use builder;

my $builder;
$builder = builder->new(author => "Author");
$builder->print();



### Package ###

package builder;

use strict;

my $author;

sub new {
   my ($class, %args) = @_;

   $author = $args{author};

   return bless(\%args, $class);
}

sub print {
   my ($self) = @_;

   print $author."\n";
}

1;


Die Frage ist wieder, was ist "richtig" bzw. "besser"? Ich würde die zweite Methode vorziehen, da die Parameter einzeln übergeben werden, wobei es aber bei vielen Werten mit den Variablen etwas unübersichtlich wird. Was meint ihr?

(Noch eine Frage am Rand: Warum wird beim bless in der zweiten Methode eine Referenz von %args genommen und bei $self nicht?)

Danke schon einmal.
Ronnie
 2007-01-31 22:57
#73898 #73898
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
Mit der zweiten variante kannst du dich böse in die Nesseln setzen, wie folgendes Beispiel zeigt:
Code: (dl )
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
#!/usr/bin/perl

use strict;

package builder;

my $author;

sub new {
my ($class, %args) = @_;
$author = $args{author};
return bless(\%args, $class);
}

sub print {
my ($self) = @_;
print $author."\n";
}

package main;

my $builder;
$builder = builder->new(author => "Author");
$builder->print();

my $b2;
$b2 = builder->new(author => "Joe");
$b2->print();
$builder->print();

Da verwendest du eine Klassenvariable, statt einer Instanzvariable. Das geht nur solange gut bis du ein zweites Objekt erzeugst!

EDIT: bei der Schreibweise der Klassennamen verwende ich zumeist CamelCase - aber das ist Geschmackssache. Ich finde das man Klassen so gut vom Rest unterscheiden kann. Laut perlstyle ist lowercase für pragmas vorgesehen.

EDIT2: http://perldoc.perl.org/perlstyle.html - der Wikitext scheint zu einer älteren Fassung von perlstyle zu gehören.

EDIT3:
Prinzipiell empfehle ich die Verwendung von CPAN:Moose, wie in folgendem Beispiel:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/perl

use strict;

package builder;
use Moose;

has 'author' => ( is => 'rw' );

package main;

my $builder;
$builder = builder->new(author => "Joe");
print $builder->author . "\n";

Man spart sich viel Arbeit mit Konstruktor und Accessoren.\n\n

<!--EDIT|Ronnie|1170277683-->
PerlProfi
 2007-01-31 23:11
#73899 #73899
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
Zu deiner ersten Frage: Normalerweise fangen Package-Namen mit einem Großbuchstaben an, also nicht builder sondern Builder.

Zu 2.:
Man legt eigentlich nicht jeweils eine Variable für ein Attribut an, sondern lässt Objektattribute auch im Objekt.

Desshalb würde ich dein 2. Beispiel einfach ein wenig umändern:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
### Package ###

package Builder;

use strict;

sub new {
my ($class, %args) = @_;

return bless(\%args, $class);
}

sub print {
my ($self) = @_;

print $self->{author}, "\n";
}

1;

Normalerweise definiert man dann noch accessor Methoden für Attribute.
Eine allgemeine Accessormethode kannst du mit AUTOLOAD definieren:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sub AUTOLOAD
{
# Objekt und neuen Wert aus der Parameterliste holen
my($self, $nv) = @_;
# Methodennamen holen
my $attr = $AUTOLOAD;

# package entfernen
$attr =~ s/.*:://;

# alten Wert holen
my $ov = $self->{$attr};
# Wert ändern, falls gewünscht
$self->{$attr} = $nv if defined $nv;

# alten Wert zurückgeben
return $ov;
}

Jetzt kann man um author zu ändern, einfach $obj->author('neuer autor'); schreiben.

Zu bless(): Weil $self schon eine Hashreferenz ist.
Lightman
 2007-01-31 23:17
#73900 #73900
User since
2007-01-31
57 Artikel
BenutzerIn
[default_avatar]
Vielen Dank für eure Antworten.

Dass man Objektattribute im Objekt lässt, habe ich mir schon fast gedacht, nur wusste ich nicht, wie man das schreibt.
Die Umsetzung mit $obj->author('neuer autor' ); scheint mir aber irgendwie "unsauber", da keine extra Methode implementiert wird.
Im Allgemeinen ist OOP mit Perl IMHO eher unsauber und wenig akademisch, wie man es von Sprachen wie z.B. Java gewohnt ist.\n\n

<!--EDIT|Lightman|1170278407-->
pq
 2007-01-31 23:18
#73901 #73901
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
AUTOLOAD fuer sowas ist altmodisch, umständlich und so, wie
du es implementiert hast, auch noch langsam =)
besser CPAN:Moose oder CPAN:Class::Acessor::Fast o.ä. verwenden.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Ronnie
 2007-01-31 23:27
#73902 #73902
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
[quote=Lightman,31.01.2007, 22:17]Im Allgemeinen ist OOP mit Perl IMHO eher unsauber und wenig akademisch, wie man es von Sprachen wie z.B. Java gewohnt ist.[/quote]
Ja, aber dafür kann man gut nachvollziehen was überhaupt passiert. Wer es akademisch mag der verwendet besser Python, oder Ruby (obwohl bei letzterem locker soviel unakademisches geschieht wie bei Perl - sieht aber dabei hübscher aus).
pq
 2007-01-31 23:33
#73903 #73903
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
wenn mans mal kapiert hat, ist perl oop huebsch, finde ich.
es ist wie bei vielen sachen in perl - ungewöhnlich; man muss es
erst mal verstehen, aber dann kann man ungeheuer schön damit
programmieren. der vorteil, dass es viele möglichkeiten gibt,
wie man es macht, ist aber natürlich gleichzeitig ein nachteil.
aber dafür gibt es ja Perl Best Practices =)\n\n

<!--EDIT|pq|1170279197-->
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Lightman
 2007-01-31 23:43
#73904 #73904
User since
2007-01-31
57 Artikel
BenutzerIn
[default_avatar]
Das Hauptproblem ist eher, dass es kaum Alternativen gibt, jedenfalls fürs Web. Auch wenn Python eine nette Sprache ist, Webanwendung überhaupt erst einmal laufen zu lassen, ist schon so eine Sache (der Behauptung, dass Web-Entwicklung mit Python nicht mehr in den Kinderschuhen steckt, würde ich wiedersprechen ;) ). Ruby ist zwar auch nett, aber da muss man seinen Hoster erst einmal überreden, mod_ruby zu installieren. ;)
Naja, und PHP ist nicht gerade ein Knaller, habe selber ein paar Jahre damit programmiert.
Strat
 2007-02-02 12:36
#73905 #73905
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
1. Namensgebung von eigenen Packages:
x) der 1. Buchstabe sollte gross sein (ein Kleinbuchstabe sollte fuer Pragmas reserviert bleiben)
x) aufpassen, dass man keinen Namen eines bereits existierenden Moduls erwischt, sonst kann - wenn mal zufaellig dieses Modul installiert wird - anstelle des eigenen Moduls das andere geladen werden, was vermutlich zu Fehlern fuehrt. Deshalb verwende ich fuer Module, die nicht via CPAN verteilt werden sollen, meist einen zweistufigen Namensraum, z.B. package MyKunde::Builder oder so
2) die erste Variante finde ich auch besser; ich wuerde sie allerdings ein klein wenig anders schreiben:
Code: (dl )
1
2
3
4
5
6
7
8
9
sub new {
my $class = shift;
my $self = bless( {}, $class ); # objekt erzeugen

# hat den vorteil, dass man z.B. eine Initialize-Methode aufrufen koennte
$self->_initialize( @_ );

return $self;
} # new


Zum Autoload: das ist ja recht nett, hat aber das Problem, dass auch die Methode DESTROY - falls nicht angegeben - automatisch erzeugt wird, und man damit ueberhaupt nicht kontrollieren kann, auf welche Attribute man zugreifen will, wodurch Tippfehler (z.B. Gross-/Kleinschreibung) schwierig zu finden werden. Also da entweder DESTROY rauskicken und ueberpruefen, auf welche Attribute ueberhaupt zugegriffen werden darf, oder die Methoden ueber eine Liste vorgenerieren und auf Autoload verzichten.
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
<< >> 9 Einträge, 1 Seite



View all threads created 2007-01-31 22:41.