Thread Konstruktorverständnis (18 answers)
Opened by leo11 at 2009-06-27 21:01

murphy
 2009-07-06 09:14
#122859 #122859
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
Mir ging es eigentlich nur um das Prinzip: Nur weil die Magie beim Zugriff nicht mehr gewünscht ist, muss die Datenstruktur nicht in jedem Falle unbrauchbar sein.

Die Magie der Pseudohashes kann man allerdings auch auf anderem Wege wieder nachbauen -- zum Beispiel mit folgender Klasse:
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package PseudoHash;

use strict;
use warnings;

use List::Util qw/max/;

# Constructor
# Params:
#   $self   = Existing object reference or package
#   @fields = Field names to be created in the new pseudo hash
# Returns:
#   A new blessed object
sub new {
  my ($self, @fields) = @_;

  my ($class, $layout) = do {
    if (my $class = ref $self) {
      ($class, $self->[0]);
    }
    else {
      ($self, {});
    }
  };

  if (@fields > 0) {
    $layout = { %$layout };
    my $offset = max(0, values %$layout) + 1;

    foreach my $field (@fields) {
      $layout->{$field} = $offset++;
    }
  }

  bless [ $layout ], $class;
}

# Accesses a field of the pseudo hash by name
# Params:
#   $self  = Reference to the pseudo hash
#   $field = Name of the field
# Returns:
#   An lvalue representing the field
sub field : lvalue {
  my ($self, $field) = @_;

  my $offset = $self->[0]->{$field};
  die "No such field '$field' in $self" unless (defined $offset);

  $self->[$offset];
}


Dazu noch ein Anwendungsbeispiel:
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
use Data::Dumper;

local ($,, $\) = (' ', "\n");

# Create a pseudo hash
my $ph = new PseudoHash(qw/FOO BAR BAZ/);

# Assign and read existing fields
$ph->field('FOO') = 42;
print 'FOO:', $ph->field('FOO');

$ph->field('BAR') = 23;
print 'BAR:', $ph->field('BAR');

# Create a pseudo hash with identical structure as $ph
my $pi = $ph->new();

# Assign and read an existing field
$pi->field('BAR') = 23;
print 'BAR:', $pi->field('BAR');

# Create a pseudo hash with structure based on $ph
my $pj = $ph->new(qw/QUARK/);

# Assign and read an existing field
$pj->field('QUARK') = 'Hallo';
print 'QUARK:', $pj->field('QUARK');

# Show the structure of the pseudo hashes
print Dumper [ $ph, $pi, $pj ];

# Try to access a non-existing field
$ph->field('BOING'); # generates an error


Wie gewünscht gibt's hier einen harten Fehler, wenn man auf nicht existierende Felder zugreift. Und natürlich kann man das oben definierte Paket PseudoHash als Basisklasse für anderen Code verwenden.
When C++ is your hammer, every problem looks like your thumb.

View full thread Konstruktorverständnis