Stevan Little <[EMAIL PROTECTED]> writes: > Hello all. > > I would like to propose that class methods do not get inherited along > normal class lines. > > I think that inheriting class methods will, in many cases, not DWIM. > This is largely because your are inheriting behavior, and not state > (since class attributes are not inheritable). Let me explain in more > detail. > > Let's start by making a very basic definition of an *object*, > ignoring any implementation details or specifics. > > object == state + behavior > > This statement assumes that *objects* at their core are a unique > state coupled with a collection of behaviors to act upon that > particular state. Of course we are ignoring all the other class/meta/ > inheritence junk for now. > > To take away the behavior, and only be left with state would degrade > our object to the level of C struct or Pascal-style record-type. To > take away the state, and only be left with behavior, would basically > leave a module/package or some pseudo-random collection of functions. > > So at this point, I think it is safe to say that an *object* should > have both state and behavior. > > Now, back down from the theoretical cloud to reality. I would like to > show some canonical class-method examples (and in some cases, show > how they are broken), then show how they might be better accomplished > in Perl 6 without the need for class methods to be inherited. > > == Instance Counting Class > > The most common example given for class methods is an "instance > counter". Here is how one might (naively) look in Perl 6: > > class A { > our $.count; > method count (Class $c:) { $.count; } > submethod BUILD { > $.count++; > } > } > > Each time an instance of A is created the counter is incremented. So > that ... > > A.count; # 0 > A.new; > A.count; # 1 > > Now this makes sense, until we subclass A. > > class B is A {} > > A.count; # still 1 > B.new; # calls A::BUILD > > A.count; # 2 > B.count; # 2 > > Clearly, we only have one instance of A, and one instance of B, so > those numbers are wrong. It could be argued that since B is a subtype > of A, we do have two A's, but the argument does not work in reverse. > But either way, I would argue that the results shown above are > misleading, and probably not what the programmer intended.
We definitely have two instances of A since, B.isa(::A). We also have a fragile implementation of count. class A { our %.count_of method count (Class $c:) { %.count_of{$c} } method BUILD { $class = ($?SELF.class) @countable_ancestors = $class.ancestors.uniq.grep :{.isa(::A)} for $class, [EMAIL PROTECTED] -> $c { %.count_of{$c}++ } } Where we're assuming I've got the syntax of 'for' right, and that 'ancestors' is a class method that returns all of a class's ancestors. This might not work too well in the face of a dynamic inheritance tree, but it should be possible to work around. Something like this might work: Class A { our %.instance_count_of method count (Class $c: ?$with_descendents = undef) { my @interesting_classes = $c; if $with_descendents { push @interesting_classes, *($c.all_subclasses); } [+] %.instance_count_of(@interesting_classes) } method BUILD { %.instance_count_of($?SELF.class) } } Where we're assuming that a class can find all its subclasses -- Piers Cawley <[EMAIL PROTECTED]> http://www.bofh.org.uk/