[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Cut AOP implementation in Ruby

Brian Takita

1/19/2006 9:06:00 PM

Hello,

Does anybody know of a Cut-based
AOP<http://www.rubygarden.org/ruby?AspectOrientedRuby&...
implemented in ruby?
I found a c-based implementation in the
Suby<http://rubyforge.org/projects/suby/&..., but I don't know if
I want to open that can of
worms.<http://www.rubygarden.org/ruby?AspectOrient...

--
Thank you,
Brian Takita
http://weblog.freeo...
1 Answer

Trans

1/19/2006 10:55:00 PM

0

A pure Ruby implementation is unfortuately far from ideal. Nonetheless
their are some appraoches that get close. Below I give one that I
developed awhile back. Also I believe Mauricio Fernandez has done some
expirementation on this too. Perhaps he has some ideas.

---- cut.rb ----

# Cut, Transparent Subclass
# Copyright (c) 2004 Thomas Sawyer
# cut.rb
#
# == Notes
#
# This implementation uses a single transparent subclass, the
ProxyCut,
# into which module mixins are included. This essentially works
# and allows cuts to be somewhat dynamic. But it does not follow the
# formal design of cuts which uses multiple transparent subclasses,
# not mixins.
#
# This implementation suffers from the dynamic module inclusion
problem.
# Due to the nature of module inclusion this is a somewhat serious
# limitation. The upshot of this is that cuts can only be defined on
# a class up to the point of instantiation. Adding subsequent cuts
# will not effect already instantiated objects. Thus all cuts to be
used
# must be defined before instantiation.

#
# = Class
#
class Class

alias_method :anew, :new

def new(*args, &blk)
proxycut.anew(*args, &blk)
end

def proxycut
@proxycut ||= ProxyCut.new(self)
end

private :proxycut

def cuts
proxycut.ancestors.select{ |a| a.is_a?(Cut) }
end

def preclude( mod )
proxycut.class_eval { include mod }
end

# this finds the nearest cut which lacks a specified method
def clearcut(meth)
#acuts = cut.ancestors.select{ |a| a.is_a?(Cut) }
r = cuts.reverse.detect{|a| !
a.instance_methods.include?(meth.to_s) }
return r
end

def wrap( meth, &meth_proc )
c = clearcut( meth )
c = Cut.new( self ) if ! c
c.send( :define_method, meth, &meth_proc )
return c
end

end


#
# = ProxyCut
#
class ProxyCut

def self.new(supclass)
Class.anew(supclass) #do
# this seems to cause problems
#alias_method :real_class, :class
#define_method(:class) { supclass }
#end
end

end


#
# = Cut
#
class Cut < Module

attr :superclass

def initialize(superclass, &block)
class_eval(&block) if block_given?
@superclass = superclass
s = self
@superclass.send(:proxycut).class_eval{ include s }
end

end


#
# = Kernel
#
module Kernel

def cut(cut_name, klass, &block)
self.class.module_eval { const_set( cut_name, Cut.new(klass,
&block) ) }
end

end



# ---- primative test ----

if __FILE__ == $0

class C
def m1; "X"; end
end

# cut A < C
A = Cut.new(C) do
def m1; "<" + super + ">"; end
end

# cut B < C
# cut B,C do
B = Cut.new(C) do
def m1; "[" + super + "]"; end
end

c = C.new

puts c.m1

p C.clearcut(:t)

p c.class

end