Schrift
[thread]10336[/thread]

OOP: mit Arrays arbeiten

Leser: 1


<< |< 1 2 >| >> 11 Einträge, 2 Seiten
Hagen
 2007-09-06 23:50
#99162 #99162
User since
2007-09-06
233 Artikel
BenutzerIn
[default_avatar]
Hallo,

seit einigen Tage 'experimentiere' ich mit OOP-Perl. Allerdings habe ich insbesondere bei Arrays ein paar Verständnisprobleme:

In meiner 'ersten' Methode habe ich einen Array mit Daten gefüttert:

Code: (dl )
1
2
3
4
5
6
sub ...1...
my @daten;
...
$daten[1] = 'Text 001';
$daten[2] = 'Text 002';
...


Mir fehlt jetzt ein Ansatz/Idee, wie ich den Array richtig speichere um in einer anderen Methode, darauf zugreifen zu können. Google, das Forum und viel Ausprobieren haben mich leider nicht weiter gebracht :-(

Mit freundlichem Gruß

Hagen[
Gruß
Hagen
pktm
 2007-09-07 00:14
#99164 #99164
User since
2003-08-07
2921 Artikel
BenutzerIn
[Homepage]
user image
Hm, also du könntest es irgendwo in deinem Objekt sepichern:
Code: (dl )
1
2
3
4
5
sub naja {
my $self = shift;

$self->{myarrayref} = [qw/1 2 3 q w e/];
} # /naja


Oder du schreibst dir getter und setter methoden:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
sub get_ding {
my $self = shift;
unless( exists $self->{'__DING'} ) {
# erstelle es
}
return $self->{'__DING'};
} # /get_ding

sub set_ding {
my $self = shift;
my $array_ref = shift;
$self->{'__DING'} = $array_ref;
} # /set_ding


Letztes kann man natürlich auch in einer Methode kombinieren. Solche Zugriffsmethoden erweisen sich bei größeren, wiederverwendbaren Skripten oft als nützlich. Zu beginn, wenn sich noch was ändern kann (ich als schlechter Programmierer arbeite immer erstmal ohne Konzept drauf los) benutze ich die erste Variante bis ich an den Punkt komme, wo ich merke dass es nützlich ist Zugriffsmethoden zu schreiben. Für jeden Firlefanz schreibe ich die aber auch nicht.

Es gibt auch Module, die dir diese Arbeit abnehmen, allerdings habe ich mich mit denen noch nicht auseinander gesetzt.

Grüße, pktm
http://www.intergastro-service.de (mein erstes CMS :) )
Linuxer
 2007-09-07 00:17
#99165 #99165
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
Hi,

was du technisch machen willst, wird mir klar, aber welche Logik dahinter steckt, warum Du das machen willst, bleibt mir verschlossen.

Wenn die erste Sub der Konstruktor ist, kannst Du den Array selber als Objekt verwenden...

Code (perl): (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
#!/usr/bin/perl
# vi:ts=4 sw=4 et:

package ups;
use strict;
use warnings;

sub new {
  my $class = shift;
  my %parms = @_;
  my $self = []; # array-ref

  push @$self, qw( abc def 123 456 );

  bless $self, $class;
  return $self;
}

sub print_content {
  my $self = shift;
  my @args = @_;
 
  for ( @$self ) {
    print $_, $/;
  }
}

package main;

my $a = ups->new();

$a->print_content();


Das Problem ist, dass der Gültigkeitsraum des Arrays @daten bei Deinem Beispiel auf den Block der Subroutine beschränkt bleibt.

Wenn Du die Daten nicht im eigentlichen Objekt speichern willst/kannst, könntest Du noch mit einem Closure arbeiten.
Aber das ist schon stärkerer Tobak, von daher würde ich dazu raten, die Daten im Objekt unterzubringen, wie pktm schon aufzeigte....

Code (perl): (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
#!/usr/bin/perl
# vi:ts=4 sw=4 et:
use strict;
use warnings;

package ups;

{  ### CLOSURE
    my @daten = (); # @daten ist nur in den Methoden bekannt, die 
                           # in diesem Block definiert werden.

    sub fill_data {
        @daten = qw( a b c 12 3 );
    }

    sub print_data {
        for ( @daten ) {
            print $_, $/;
        }
    }
}

sub new {
    my $class = shift;
    my %parms = @_;
    my $self = {};

    bless $self, $class;
    return $self;
}

package main;

my $obj = ups->new();

$obj->fill_data();
$obj->print_data();
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
Hagen
 2007-09-07 00:29
#99166 #99166
User since
2007-09-06
233 Artikel
BenutzerIn
[default_avatar]
Wow, das geht ja schnell hier, super!

Also, so ganz habe ich die Lösungen noch nicht verstanden, das kommt aber daher, dass ich sie bisher nur überflogen haben. Das 'durcharbeiten' kommt aber jetzt.

Wie schon geschrieben, fange ich so langsam mit dem Thema OOP an, daher kann in der Lösung auch noch ein Denkfehler liegen.

In der ersten Methode (scan) wird der Array nach bestimmten Kriterien mit Dateinamen aus einem Verzeichnis gefüllt ($daten-Array; dort stehen auch noch weitere Informationen zu den Dateien). Mit der zweiten Methode (get) wird jeweils ein Eintrag heraus geholt und je nach Parameter als 'bearbeitet' markiert.

Habe das ganz als Aufabe zum einarbeiten in das Thema OOP genommen.

Gruß

Hagen
Gruß
Hagen
Linuxer
 2007-09-07 00:37
#99167 #99167
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
Hi,

wenn Du anfängst, dann stell meinen Ansatz mit dem Closure ganz nach hinten (und schieb ihn dann noch etwas weiter ;o) ).
Konzentrier Dich auf den Ansatz, den Dir pktm aufzeigte. Der Ansatz ist nochmal ein Stück besser als mein erster.
Wenn Dir was unklar ist, scheu Dich nicht zu fragen ;)
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
Hagen
 2007-09-07 12:17
#99186 #99186
User since
2007-09-06
233 Artikel
BenutzerIn
[default_avatar]
Habe es dann 'geschafft', indem ich die Referenz des Arrays gespeichert habe (wie von ptkm vorgeschlagen). Aber ich verstehe nicht, warum das funktioniert.

Wenn ich 'normal' (nicht OOP) einen Funktion (sub) benutzte und darin wird ein Array lokal definiert (my @daten), dann besteht *dieser* Array nur für einen Aufruf. D.h. wenn ich die Funktion ein zweites mal benutzte, kann nicht auf die alten Inhalte zugegriffen werden.

Technisch wird doch der Speicherbereich des Arrays nach Beendigung der Funktion wieder frei gegeben, weil er nur für die Funtkion/Aufruf (wg. 'my') reserviert wurde.

Aber warum funktioniert das bei meinem Problem (s.o.)? Ich hätte erwartet, dass in 'sub ...1...' zwar der Array definiert, mit Inhalt gefüllt und eine Referenz gespeichert wird.
Wenn man aber in 'sub ...2...' mittels der Referenz (das ist doch nur eine Speicheradresse) auf die Daten zugreifen möchte, man sehr wahrscheinlich nur Datenmüll erhält, vielleicht zufällig das gesuchte.

Gruß

Hagen
Gruß
Hagen
renee
 2007-09-07 12:29
#99188 #99188
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Garbage Collection in Perl läuft so, dass die Referenzen gezählt werden. Und der Inhalt des Speichers geht nur dann "verloren" wenn der Referenzzähler auf "0" steht, das heißt keine Stelle im Programm mehr auf den Speicher zeigt. Wenn Du ein Programm hast, in dem es heißt

Code (perl): (dl )
1
2
3
4
sub test{
    my @array = (1..10);
    # mach was mit @array
}


dann wird in Zeile 2 das Array angelegt und Speicher freigehalten. Der Referenzzähler ist dann "1". Wenn die Subroutine verlassen wird, wird das Array "zerstört", der Referenzzähler wird auf "0" gesetzt. Der Speicher wird freigegeben und Du kommst nicht mehr an den Inhalt ran.

Wenn Du so etwas machst:
Code (perl): (dl )
1
2
3
4
5
6
my $arref = test();

sub test{
    my @array = (1..10);
    return \@array;
}


dann wird bei der Initialisierung des Arrays wieder der Referenzzähler auf "1" gesetzt. Durch die Erzeugung der Referenz beim "return" wird der Referenzzähler auf "2" gesetzt. Beim Verlassen der Sub existiert zwar "@array" nicht mehr (der Referenzzähler wird auf "1" gesetzt), aber die Referenz, die mittels "\@array" erzeugt wurde, existiert in $arref ja weiter. Da der Referenzzähler != 0 ist, wird der Speicher nicht freigegeben und Du kommst über die Referenz noch an den Inhalt.

Lesenswert zu diesem Thema ist "Intermediate Perl" Kapitel 5
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Linuxer
 2007-09-07 13:28
#99191 #99191
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
renee+2007-09-07 10:29:43--
Wenn Du ein Programm hast, in dem es heißt

Code (perl): (dl )
1
2
3
4
sub test{
    my @array = (1..10);
    # mach was mit @array
}


dann wird in Zeile 2 das Array angelegt und Speicher freigehalten. Der Referenzzähler ist dann "1". Wenn die Subroutine verlassen wird, wird das Array "zerstört", der Referenzzähler wird auf "0" gesetzt. Der Speicher wird freigegeben und Du kommst nicht mehr an den Inhalt ran.


Ist die geschilderte Reihenfolge nicht falsch?
Die Referenzzählung muss ja vor dem Zerstören des Arrays erfolgen, also wäre es besser so zu schreiben:
Wenn die Subroutine verlassen wird, wird der Referenzzähler für das Array auf "0" gesetzt. Weil der Referenzzähler 0 ist, wird das Array wird zerstört und der Speicher freigegeben.
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
renee
 2007-09-07 13:49
#99192 #99192
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Ich kenne die Perl-Internas auch nicht 100%ig, aber wenn ich es richtig verstanden habe, wird der "Eintrag" für das Array aus der internen Tabelle gelöscht. Das "Löschen" beinhaltet, dass der Referenzzähler um 1 verringert wird. Ist der Eintrag dann 0, wird der Speicher freigegeben...

Mit "... das Array wird gelöscht..." meinte ich nicht die Einträge, sondern der Eintrag für "@array".
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Hagen
 2007-09-07 15:26
#99195 #99195
User since
2007-09-06
233 Artikel
BenutzerIn
[default_avatar]
Danke für die Infos (bzgl. Arrays und Refrenzen), jetzt wird so einiges klarer :-)

Gruß

Hagen
Gruß
Hagen
<< |< 1 2 >| >> 11 Einträge, 2 Seiten



View all threads created 2007-09-06 23:50.