From: Tom B. <Tom.Ball@Sun.COM> - 2003-09-17 19:20:34
|
I want to create a Jython class that subclasses a Java class which has overloaded methods: public class NodeVisitor { public void visit(Node v); public void visit(VarNode v); public void visit(ClassNode v); ... } (As you probably guessed, this uses the Gof4 Visitor pattern. :-) What would a Jython subclass's visit method look like? I'm stumped. Thanks in advance, Tom |
From: Oti <oh...@ya...> - 2003-09-17 19:54:21
|
[ Tom Ball ] > I want to create a Jython class that subclasses a Java class which > has > overloaded methods: > > public class NodeVisitor { > public void visit(Node v); > public void visit(VarNode v); > public void visit(ClassNode v); > } > > (As you probably guessed, this uses the Gof4 Visitor pattern. :-) > > What would a Jython subclass's visit method look like? I'm stumped. Hello Tom, consider the following files ------------------------------------------------ NodeVisitor.java: ----------------- package test; public abstract class NodeVisitor { public abstract void visit(Node v); public abstract void visit(VarNode v); public abstract void visit(ClassNode v); } Node.java: ---------- package test; public class Node {} VarNode.java: ------------- package test; public class VarNode {} ClassNode.java: --------------- package test; public class ClassNode {} NodeVisitorImpl.py: ------------------- from test import ClassNode from test import Node from test import NodeVisitor from test import VarNode class NodeVisitorImpl(NodeVisitor): def visit(self, node): print "visited %s" % node.__class__ if isinstance(node, Node): print " this was a Node" elif isinstance(node, VarNode): print " this was a VarNode" elif isinstance(node, ClassNode): print " this was a ClassNode" if __name__ == '__main__': nvi = NodeVisitorImpl() nvi.visit(Node()) nvi.visit(VarNode()) nvi.visit(ClassNode()) ------------------------------------------------ then the command jython NodeVisitorImpl.py leads to: visited test.Node this was a Node visited test.VarNode this was a VarNode visited test.ClassNode this was a ClassNode AFAIK: you are lucky if the abstract methods have only one parameter. If there are more than one parameters, and abstract methods are overloaded, you might get into trouble implementing them in Jython (I'd love to see examples, though). On the other hand, if all methods are concrete, you just implement the methods with different parameter counts and test the types as in the example above. Hope to have helped a bit, and best wishes, Oti. __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com |
From: Tom B. <Tom.Ball@Sun.COM> - 2003-09-17 21:10:54
|
Thank you very much, my script is now up and starting to run. One more minor question: is it possible to import public inner classes? My script works with MyClass.Node, MyClass.VarNode, etc., but I haven't found an import statement that allows references to just Node, VarNode, etc. If not, it's no big deal... Thanks again, Tom On Wed, 2003-09-17 at 12:53, Oti wrote: > [ Tom Ball ] > > I want to create a Jython class that subclasses a Java class which > > has > > overloaded methods: > > > > public class NodeVisitor { > > public void visit(Node v); > > public void visit(VarNode v); > > public void visit(ClassNode v); > > } > > > > (As you probably guessed, this uses the Gof4 Visitor pattern. :-) > > > > What would a Jython subclass's visit method look like? I'm stumped. > > Hello Tom, > > consider the following files > ------------------------------------------------ > > NodeVisitor.java: > ----------------- > package test; > public abstract class NodeVisitor { > public abstract void visit(Node v); > public abstract void visit(VarNode v); > public abstract void visit(ClassNode v); > } > > Node.java: > ---------- > package test; > public class Node {} > > VarNode.java: > ------------- > package test; > public class VarNode {} > > ClassNode.java: > --------------- > package test; > public class ClassNode {} > > NodeVisitorImpl.py: > ------------------- > from test import ClassNode > from test import Node > from test import NodeVisitor > from test import VarNode > > class NodeVisitorImpl(NodeVisitor): > def visit(self, node): > print "visited %s" % node.__class__ > if isinstance(node, Node): > print " this was a Node" > elif isinstance(node, VarNode): > print " this was a VarNode" > elif isinstance(node, ClassNode): > print " this was a ClassNode" > > if __name__ == '__main__': > nvi = NodeVisitorImpl() > nvi.visit(Node()) > nvi.visit(VarNode()) > nvi.visit(ClassNode()) > ------------------------------------------------ > > then the command > jython NodeVisitorImpl.py > leads to: > visited test.Node > this was a Node > visited test.VarNode > this was a VarNode > visited test.ClassNode > this was a ClassNode > > > AFAIK: > you are lucky if the abstract methods have only one parameter. If there > are more than one parameters, and abstract methods are overloaded, you > might get into trouble implementing them in Jython (I'd love to see > examples, though). > On the other hand, if all methods are concrete, you just implement the > methods with different parameter counts and test the types as in the > example above. > > > Hope to have helped a bit, and best wishes, > Oti. > > __________________________________ > Do you Yahoo!? > Yahoo! SiteBuilder - Free, easy-to-use web site design software > http://sitebuilder.yahoo.com |
From: Oti <oh...@ya...> - 2003-09-22 19:27:19
|
[ Tom Ball ] > Thank you very much, my script is now up and starting to run. you're welcome. > One more minor question: is it possible to import public inner > classes? My script works with MyClass.Node, MyClass.VarNode, etc., > but > I haven't found an import statement that allows references to just > Node, > VarNode, etc. If not, it's no big deal... AFAIK direct import is not possible, but you can reference them from the outer class. The following mini example demonstrates this: Outer.java: ----------- package test; public class Outer { public static class StaticInner {} public class Inner {} } jython Jython 2.1 on java1.4.2 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> from test import Outer >>> Outer <jclass test.Outer at 26596606> >>> Outer.StaticInner <jclass test.Outer.StaticInner at 31601333> >>> Outer.Inner <jclass test.Outer.Inner at 20736546> >>> Best wishes, Oti. |
From: Jim H. <li...@hu...> - 2003-09-23 16:56:48
|
> [ Tom Ball ] >>I want to create a Jython class that subclasses a Java class which >>has >>overloaded methods: >> >>public class NodeVisitor { >> public void visit(Node v); >> public void visit(VarNode v); >> public void visit(ClassNode v); >>} >> >>(As you probably guessed, this uses the Gof4 Visitor pattern. :-) >> >>What would a Jython subclass's visit method look like? I'm stumped. Oti offered a great solution to this problem already. Nonetheless, I'd like to chime in with a different approach that uses python's meta-programming facilities to automatically produce a visitor class for any collection of targets. For each object passed to the visit method, this class will look for a corresponding method with the name 'visit_SimpleClassName', where SimpleClassName is the part of the class's name after any dots. If no method is found, then the class's first direct superclass is checked recursively. It's left as an exercise to the reader to implement a reasonable method resolution algorithm for multiple supertypes. The method for any given class is cached in a dictionary so the performance of the class should be close to or better than a hand-coded visitor. BTW - An advantage of this over the traditional GoF visitor is that you can easily write visit methods at any level of your type hierarchy. I find this is very helpful when experimenting with ASTs. --------------------- class Visitor: """ >>> from java.io import * >>> from java.math import * >>> v = Visitor() >>> v.visit(BigInteger("2")) BigInteger 2 >>> v.visit(BigDecimal("2.2")) Number 2.2 >>> v.visit(File("foo")) Object foo """ def visit_Object(self, node): print 'Object', node def visit_Number(self, node): print 'Number', node def visit_BigInteger(self, node): print 'BigInteger', node def __init__(self): self.dispatch_table = {} def lookup_visit_method(self, clazz): name = "visit_" + clazz.__name__.split('.')[-1] meth = getattr(self, name, None) if meth is not None: return meth if len(clazz.__bases__) == 0: return None else: return self.lookup_visit_method(clazz.__bases__[0]) def visit(self, node): meth = self.dispatch_table.get(node.__class__, None) if meth is None: meth = self.lookup_visit_method(node.__class__) assert meth is not None, ( 'no visit method for ' + str(node.__class__)) self.dispatch_table[node.__class__] = meth return meth(node) --------------------------------------- Jim Hugunin -- http://hugunin.net |