Schrift
[thread]7081[/thread]

Dispatch Table mit Objekten: Objektmethoden statt funktionen



<< >> 9 Einträge, 1 Seite
Damokles
 2005-06-28 15:42
#55759 #55759
User since
2005-06-28
7 Artikel
BenutzerIn
[default_avatar]
Hallo, ich möchte eine dispatch table mit methoden einer Klasse anstelle mit normalen funktionen haben. Es geht dabei um einen Paket Parser.

Normale dispatch tables sehen so aus.

Code: (dl )
1
2
3
4
5
6
7
8
%packets_processors = (
   ...,
   "0110" => \&skill_failed,
   "0114" => \&skill_used,
   "01DE" => \&skill_used,
   "0117" => \&skill_used_on_coordinates,
   ...
);


Da ich aber eine Klasse verwende, weil es verschiedene Server mit unterschiedlichen Paketen sein können, kann ich keine einfachen funktionsreferenzen machen. Mit eval geht es zwar, aber das würde den geschwindigkeitsvorteil der dispatch table gegenüber dem if-else switch wieder vernichten. Ich hab schon rausgefunden, dass man funktionen wie unten beschrieben auch ohne eval benutzen kann. Aber bei Objekten habe ich es noch nicht geschaft.

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ cat call_function_by_name.pl 
use strict;

sub foo {
       my $arg = shift;

       print "You called foo($arg)\n";
}

my $bar = 'foo';
{
       no strict 'refs';
       &$bar(5);
}
$ perl call_function_by_name.pl
You called foo(5)


Wißt ihr einen weg?\n\n

<!--EDIT|Damokles|1119959014-->
Strat
 2005-06-28 18:06
#55760 #55760
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
wenn es sich um objektmethoden handelt, meinst du vielleicht sowas?
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
my %dispatch = (
1 => 'doOne',
2 => 'doTwo',
3 => 'doThree',
);
my $action = 1;
my $class = "XYZDASDF";
my $object = $class->new();
if (exists $dispatch{$action}) {
$object->$dispatch{$action};
}
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
kabel
 2005-06-28 18:09
#55761 #55761
User since
2003-08-04
704 Artikel
BenutzerIn
[default_avatar]
[quote=Damokles,28.06.2005, 13:42]Ich hab schon rausgefunden, dass man funktionen wie unten beschrieben auch ohne eval benutzen kann. Aber bei Objekten habe ich es noch nicht geschaft.[/quote]

dreimal darfst du raten, was &$bar(5) macht ;)
-- stefan
Strat
 2005-06-28 18:10
#55762 #55762
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
da ja eine methode eine subroutine ist, als deren erster Parameter entweder ein String(Klasse) oder eine Referenz (ein Objekt) ist, koennte man vielleicht auch mal ueber folgendes nachdenken:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
my %dispatch = (
 1 => \&XYDFASDF::doOne,
 2 => \&XYDFASDF::doTwo,
 3 => \&XYDFASDF::doThree,
);
my $action = 2;
my $object = XYDFASDF->new();
if (exists $dispatch{$action}) {
 $dispatch{$action}->($object);
}

aber sowas widerspricht eigentlich OOP, und erschwert auch einiges wie z.B. vererbung\n\n

<!--EDIT|Strat|1119967896-->
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
pq
 2005-06-28 19:04
#55763 #55763
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
strat, wieso so umständlich? ist doch einfach:
Code: (dl )
1
2
3
my $coderef = $object->can("gewuenschte_methode");
# oder my $coderef = $dispatch{...};
$object->$coderef(@args);
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
Gast Gast
 2005-06-28 19:06
#55764 #55764
Warum nicht einfach sub { $obj->methode (@_) } als Callback? Da kann man noch zusätzliche Parameter setzen ;)
Damokles
 2005-06-28 20:26
#55765 #55765
User since
2005-06-28
7 Artikel
BenutzerIn
[default_avatar]
Danke leute hat mir echt geholfen.
Wusste nicht das es in Perl so einfach ist.

----
Hm habs jetzt mal ausprobiert, hab aber Schwierigkeiten Parameter zu übergeben.

Code: (dl )
1
2
3
4
5
my $inst = child->new();

my %foo = (0110 => 'decode',a=>'Hallo ',b=>'Welt!!!');
my $bar = $inst->can('decode');
$inst->$bar(211,'hallo','xg',\%foo);


decode sollte einfach nur die parameter ausgeben, aber es passiert nichts.\n\n

<!--EDIT|Damokles|1119977440-->
pq
 2005-06-28 22:12
#55766 #55766
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
dann machst du was verkehrt:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
$ perl -wle'
sub child::decode {
print "decode(@_)"
}
my %foo = (0110 => "decode",a=>"Hallo ",b=>"Welt!!!");
my $inst = bless {}, "child";
my $bar = $inst->can("decode");
$inst->$bar(211,"hallo","xg",\%foo);
'
decode(child=HASH(0x813c8a4) 211 hallo xg HASH(0x813c9a0))
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
Damokles
 2005-06-29 00:30
#55767 #55767
User since
2005-06-28
7 Artikel
BenutzerIn
[default_avatar]
Ah hab meinen Fehler gefunden, decode war in der parent Klasse und hatte die parameter nicht an meine process funktion weitergegeben.

Danke für die Geduld. :D
<< >> 9 Einträge, 1 Seite



View all threads created 2005-06-28 15:42.