#!/usr/bin/perl use strict; use warnings; ######################################################################## package can_plugin; use attributes; BEGIN { my %found; sub MODIFY_CODE_ATTRIBUTES { my $pkg = shift; my $ref = shift; next unless grep{ /^PLUGIN_OVERWRITE$/ }@_; $found{$pkg}{$ref}++; return; } sub __INIT__ { for my $pkg (keys(%found)) { no strict 'refs'; while(my ( $name , $symbol ) = each %{ $pkg . '::' }) { no warnings 'once'; my $ref = *{ $symbol }{ CODE } or next; next unless($found{$pkg}{$ref}); no warnings 'redefine'; *{ $pkg . '::' . $name } = sub { { my $fname=$name; my $self=$_[0]; for my $plugin (@{$self->{__PLUGIN__ISA}}) { if( $plugin->can($fname) ) { goto &{$plugin . '::' . $fname}; } } } goto $ref; } # sub end } } } } INIT{ __PACKAGE__->__INIT__(); } sub add_plugins { my $self=shift; for(@_) { unshift(@{$self->{__PLUGIN__ISA}},$_) if($_); } } 1; ######################################################################## ################################################################### package plugin::A; sub SAVE { print "SAVE von plugin::A($_[0]->{val})\n"; } 1; ################################################################### package plugin::B; sub LOAD { print "LOAD von plugin::B($_[0]->{val})\n"; } 1; ################################################################### package plugin::C; sub CONVERT { print "CONVERT von plugin::C($_[0]->{val})\n"; } 1; ################################################################### package klasse; use base 'can_plugin'; sub new { my $class=shift; my $val=shift; my $self={ val => $val }; return bless($self,$class); } sub SAVE : PLUGIN_OVERWRITE { print "SAVE von klasse($_[0]->{val})\n"; } sub LOAD : PLUGIN_OVERWRITE { print "LOAD von klasse($_[0]->{val})\n"; } sub CONVERT : PLUGIN_OVERWRITE { print "CONVERT von klasse($_[0]->{val})\n"; } 1; ################################################################### ################################################################### ################################################################### package main; my $k1=klasse->new('A'); $k1->add_plugins(qw ( plugin::B plugin::C )); $k1->LOAD(); $k1->SAVE(); $k1->CONVERT(); my $k2=klasse->new('B'); $k2->add_plugins(qw ( plugin::A plugin::C )); $k2->LOAD(); $k2->SAVE(); $k2->CONVERT();