views:

304

answers:

5
public abstract class Master
{
    public void printForAllMethodsInSubClass()
    {
        System.out.println ("Printing before subclass method executes");
            System.out.println ("Parameters for subclass method were: ....");
    }
}

public class Owner extends Master {
    public void printSomething () {
        System.out.println ("This printed from Owner");
    }

    public int returnSomeCals ()
    {
        return 5+5;
    }
}

Without messing with methods of subclass...is it possible to execute printForAllMethodsInSubClass() before the method of a subclass gets executed?

update:

Using AspectJ/Ruby/Python...etc Would it also be possible to print the parameters? Above code formatted below: public abstract class Master { public void printForAllMethodsInSubClass() { System.out.println ("Printing before subclass method executes");

    }
}

public class Owner extends Master {
    public void printSomething (String something) {
        System.out.println (something + " printed from Owner");
    }

    public int returnSomeCals (int x, int y)
    {
        return x+y;
    }
}
+6  A: 

AspectJ can provide this functionality for you, but it's a separate compilation step and some extra libraries involved.

public aspect ServerLogger {
    pointcut printSomething ();

    before(): printSomething()
    {
            (Master)(thisJoinPointStaticPart.getTarget()).printForAlMethodsInSubClass();
    }
}

The Eclipse Project provides a great implementation of AspectJ that integrates nicely with Eclipse and Maven. There's a boatload of great documentation available for it, and a lot of really good material for it here on StackOverflow.

[update]

To access parameter info, you can use the

thisJoinPoint.getSignature(); 

method to access information about the function being called if the returned Object is an instance of MethodSignature, you can use Signature.getParameterNames() to access the parameters to the function being called. You'd have to use a bit of reflection to actually get at the values, I think - AspectJ doesn't seem to handle this for you. I'd have to actually do some experimentation to get some working code for you.

Chris Kaminski
I am not familiar with AspectJ at all. can you provide any particular links that would explain this?
drake
http://eclipse.org/aspectj/
Lord Torgamus
thanks. will have to look at aspectJ. seems like whole other world I was unaware of. one liner question though. Can aspectJ be utilized in J2EE like applications?
drake
@drake: absolutely. You can use AspectJ in any 1.4/1.5+ environment, from standalone AWT/Swing apps, to J2EE. You find plenty of examples using it from basic servlets all the way to Spring apps.
Chris Kaminski
@chris thanks. I'm reading up AspectJ in action book now. Question: would it also be able to print out all the parameter values of the subclass method? please see update
drake
@drake: see update.
Chris Kaminski
+1  A: 

This is possible in aspect-oriented programming languages, such as AspectJ.

Matthew Flaschen
+2  A: 

To answer the "any other programming language": It's easily possible in Ruby:

class Master
  REDEFINED = []
  def printForAllMethodsInSubClass
    puts 'Printing before subclass method executes'
  end

  def self.method_added(meth)
    if self < Master and not Master::REDEFINED.include? meth
      new_name = "MASTER_OVERRIDE_#{meth}".intern
      Master::REDEFINED.push meth, new_name
      alias_method new_name, meth
     define_method(meth) {|*args| printForAllMethodsInSubClass; send(new_name, *args)}
    end
  end
end

You could also make a proxy declaration method to use in subclasses:

class Master
  def printForAllMethodsInSubClass
    Printing before subclass method executes
  end

  def self.master_method(name)
    define_method(name) {|*args| printForAllMethodsInSubClass; yield *args}
  end
end

class Owner
  master_method(:print_something) do
    puts "This was printed from Owner"
  end
end

(This approach would also translate very naturally to Python decorators.)

Chuck
Thanks. I was interested in seeing how functional programming languages would do this. Would it be possible to print parameter values as well? please see update
drake
tried your code http://pastie.org/860085 but it fails and uses massive memory....is my implementation wrong?
drake
Nope, my mistake. I don't do `method_added` metaprogramming that much, forgot one of its quirks and didn't have time to test. Will fix.
Chuck
holy shit. i dont know at all what that means. will poke around
drake
A: 

In Python you can accomplish this using meta classes, here's a small example. You can probably make it more elegantly but it is just to make the point

import types

class PrintMetaClass(type):
  def __init__(cls, name, bases, attrs):
    # for every member in the class
    override = {}
    for attr in attrs:
        member = attrs[attr]
        # if it's a function
        if type(member) == types.FunctionType:
          # we wrap it 
          def wrapped(*args, **kwargs):
            print 'before any method'
            return member(*args, **kwargs)
          override[attr] = wrapped
    super(PrintMetaClass, cls).__init__(name, bases, attrs)
    for attr in override:
      setattr(cls, attr, override[attr])

class Foo:
    __metaclass__ = PrintMetaClass
    def do_something(self):
        print 2

class Bar(Foo):
    def do_something_else(self):
        print 3

In this example, the PrintMetaClass gets in the way of the creation of the Foo class and any of its subclasses redefining every method to be a wrapper of the original and printing a given message at the beginning. The Bar class receives this aspect-like behavior simply by inheriting from Foo which defines its __metaclass__ to be PrintMetaClass.

Metaclasess in OOP:

Metaclasses in python:

Santi P.
have not dabbled into python at all. but i will give this a try. thanks
drake
A: 

Besides aspect oriented programming have a look at Template Method Pattern, http://en.wikipedia.org/wiki/Template_method_pattern.

In short: the parent class have an abstract method, which subclasses have to implement, this abstract method is called by a method in the parent class where put your printouts or whatever necessary statements.

Kennet