sub Listable::insert { my ($self, $child) = @_; die "Cannot insert ", ref($child), " into a ", ref($self) unless $self->is_legal_to_insert($child); push @{$self}, $child; } sub Listable::insert { return 1; } sub Matrices::is_legal_to_insert { my ($self, $child) = @_; return 1 if $child->isa( 'Matrix' ); return $self->SUPER::is_legal_to_insert( $child ); }
Each class gets a bite at the apple to say if such'n'such is legal or not to insert. Now, I chose to make a definition based on the fact that I'm assuming "Matrices" are only allowed to contain items of type "Matrix". You could say "Foo" is allowed to have everything except "Bar", in which case that would look like:
sub Foo::is_legal_to_insert { my ($self, $child) = @_; return 0 if $child->isa( 'Bar' ); return $self->SUPER::is_legal_to_insert( $child ); }
Now, in this solution, you will always want to redispatch to your parent if you don't have an opinion on the matter. This is because you never know if today's parent will be your parent or your grandparent tomorrow. This way, you're refactor-proof.
Now, we're asking the container if it's allowed to hold children of that class. Another option would be to ask the children if they're allowed to be held by that type of container. That may not make sense for your current project, but it's an option that you should be conceptually familiar with.
In reply to Re: "polymorphism" hack: nuts or wise?
by dragonchild
in thread "polymorphism" hack: nuts or wise?
by rvosa
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |