Hi Fellow Monks!
I've been developing yet another shell for about a month or so. As I'm trying to make it as subclassable as possible, I'm defining more classes than I thought I would. To deal with this, I have a global data class from which all my classes inherit from.

I looked for a module on CPAN that would create class data (via accessors) which parent and children classes could read, write and create. I thought Class::Data::Inheritable would do the trick but it doesn't allow children classes to create or modify data that parent classes can see. So I ended modifying it some by making class data accessors always access the same class.

I'm supplying the module I made and wonder if other monks think it's useful and unique enough to be up on CPAN

package Class::Data::Global; use strict qw/vars subs/; use vars qw/$names $global_class/; our $version ='0.1'; #functions #this method is a copy from Class::Data::Inheritable sub mk_cdata { my ($declaredclass, $attribute, $data) = @_; my $accessor = sub { my $wantclass = ref($_[0]) || $_[0]; #could put this statement after $data = in order for parent #modification + then break #return $wantclass->mk_cdata($attribute)->(@_) # if @_>1 && $wantclass ne $declaredclass; #commented to have a global constant data source $data = $_[1] if @_>1; return $data; }; push(@{$names},$attribute); *{$declaredclass.'::'.$attribute} = $accessor; my $alias = "_${attribute}_accessor"; *{$declaredclass.'::'.$alias} = $accessor; } sub mk_many { my ($class,%args) = @_; while (my ($key,$value) = each %args) { $class->mk_cdata($key=>$value); } } sub setmany { my ($class,%args) = @_; while (my ($k,$v) = each %args) { $class->$k($v) || die "can't set $k"; } } sub getmany { my $class = shift; my @return; for (@_) { push(@return,$class->$_); } return @return; } sub mk_cdata_global { my $childclass = shift; __PACKAGE__->global_class->mk_cdata(@_); } sub mk_many_global { my ($class,%args) = @_; while (my ($key,$value) = each %args) { $class->mk_cdata_global($key=>$value); } } sub check_or_mk_global { my ($class,%choices) = @_; while (my ($k,$v) = each %choices ) { #($class->can($k) && $class->$k($v)) || $class->mk_cdata_global( +$k=>$v); $class->can($k) || $class->mk_cdata_global($k=>$v); } } #todo: method to set global class __PACKAGE__->mk_cdata(global_class=>__PACKAGE__); sub get_names { #use Data::Dumper; #for (@{$names}) { print "$_\n"; my $temp = __PACKAGE__->$_; print + Dumper $temp } print join(' ',@{$names}),"\n"; } 1; __END__ =head1 NAME Class::Data::Global - Handles global class data that both parent and c +hild classes can read,write and create. =head1 SYNOPSIS package Family; use base 'Class::Data::Global'; Family->mk_cdata(father=>'Homer'); Family->mk_many(mother=>'Marge',children=>{son=>'Bart',daughter=>'Li +sa',baby=>'Maggie'}); package Simpsons; use base 'Family'; print "When the's the last time you saw ", Simpsons->father," strang +le ", Simpsons->children->{son},"?\n"; Simpsons->mk_cdata_global(coworkers=>[qw/Lenny Carl/]); Simpsons->mk_many_global(gangster=>'Tony',dog=>'Brian'); package FamilyGuy; use base 'Family'; FamilyGuy->setmany(father=>'Peter',mother=>'Lois',children=>{son=>'C +hris',daughter=>'Meg',baby=>'Stewie'}); my ($father,$children) = FamilyGuy->getmany(qw/father children/); print "Who's dumber, ",$children->{son}," or $father ?\n"; print "Who's smarter, ",$children->{baby}," or ",FamilyGuy->dog,"?\n +"; FamilyGuy->check_or_mk_global(father=>'Homer'); =head1 DESCRIPTION This module creates accessors/mutators for global and local class data +. The accessors access scalar values which can hold references to any da +ta type. From the above example, class data coworkers and children contain refe +rences to an array and hash respectively. Global class data can be read,written and created by child classes as +well as the parent class. As global implies, all classes see the same value for a given accessor. For example, &mk_many_global makes a global data accessor f +or dog which is later used in the class FamilyGuy. Local class data can be read and written by the parent class and its c +hildren but can't be created by the children. If you're looking for local clas +s data that children classes can't change then look at Class::Data::Inheritab +le. An above example of local class datum is 'father' which is defined in +the class Family and later redefined in class FamilyGuy. =head1 Class Methods Note: a [] around a data type in a function definition means its req +uired mk_cdata([$name],$value) __PACKAGE__->mk_cdata(boss=>'Smithers'); This method is the base accessor constructor. Use it for making a local class accessor. mk_many([%name_value_pair]) __PACKAGE__->mk_many(bartender=>'Moe',silly_cop=>'Chief Wigams'); A macro of mk_cdata to make several local class constructors in one call. mk_cdata_global([$name],$value) __PACKAGE__->cdata_global(nerd=>'Milhouse'); Method to create a global class accessor. mk_many_global([%name_value_pair]) __PACKAGE__->mk_many_global(clown=>'Krusty',bully=>'Nelson'); A macro of mk_cdata_global to create several global class accessor +s in one call. setmany([%name_value_pair]) __PACKAGE__->setmany(); A macro to set several constructors in one call. getmany([@names]) my ($family,$father,$coworkers) = __PACKAGE__->(qw/family father c +oworkers/); A macro to return an array of values for given accessors. check_or_mk_global([%name_value_pair]) __PACKAGE__->check_mk_global(bully=>'Nelson',merchant=>'Apu'); Checks to see if the given accessor(s) exist. If they don't, then +they are created. =head1 TODO Making a method (global_class()) that sets the class in which all glob +al class data is defined. =head1 AUTHOR Me. Gabriel that is. If you want to bug me with a bug: cldwalker@chwha +t.com If you like using perl,linux,vim and databases to make your life easie +r (not lazier ;) check out my website at www.chwhat.com. =head1 LICENSE This library is free software; you can redistribute it and/or modify i +t under the same terms as Perl itself.
Also, what other ways can you keep track of application-wide class data without making all other classes inherit from a global data class?

Thanks for your thoughts.


In reply to global class data by cldwalker

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.