overloading with generic arguments

Discussion in 'Java' started by Hendrik Maryns, Jan 9, 2007.

  1. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    Hi,

    I have a complicated question about overloading with generic arguments.
    I could not find a satisfying answer in Angelika Langer’s generics FAQ
    (http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html), or in
    Sun’s generics tutorial
    (http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf). I hope
    someone here can read better than me.

    I have a class which implements a DAG with labelled edges (actually an
    MDD). Recently, I decided I needed non-determinism, so multiple edges
    starting from one node can have the same label. This also requires the
    possibility of there being more than one root (this will occur due to
    certain manipulations of the DAG, such as removing a certain layer,
    which can be the root layer).

    This is implemented by Nodes which have children and so on. These are
    inner classes and interfaces of a wrapping class, which stores the root
    and offers manipulations of the DAG. This class used to have the
    following simple layout:

    public class CompactFunction {

    private Node root;

    public CompactFunction(Node root){
    this.root = root;
    }

    public CompactFunction(BidiNode root){
    this.root = root.getUnidirNode();
    }

    public CompactFunction removeVariable(int index) {...}

    // more functions for manipulating and evaluating the function.

    public interface Node {
    // methods for all nodes
    }

    public class NonTerminalNode {
    // nodes which have children, with methods to manipulate // the children
    }

    public class TerminalNode {
    // nodes which have no children, but store a value
    }
    }

    BidiNode is a node which also points up to its parents, and is used in
    the construction of the DAG. Once it is constructed, I want to remove
    the now no longer relevant information of the up-pointers, which is done
    in the method getUnidirNode().

    Now introducing nondeterminism seems simple: change root into a set of
    nodes, alter the constructors and make all methods loop through the set
    of nodes, as necessary. The problem is the second point; with the
    following declaration:

    CompactFunction(Set<BidiNode> roots) {
    for (NonTerminalBidiNode root : roots) {
    this.roots.add(root.getUnidirNode());
    }
    }

    CompactFunction(Set<Node> roots) {
    this.roots.addAll(roots);
    }

    Eclipse gives me the following errors:

    Duplicate method CompactFunction(Set<CompactFunctionBuilder.BidiNode>)
    in type CompactFunction

    for the first constructor, and

    Duplicate method CompactFunction(Set<CompactFunction.Node>) in type
    CompactFunction

    for the second one. I suppose this is because erasure makes the method
    signatures the same, but I thought overloading was handled by the
    compiler, so this should work fine, right?

    So the question: are these error messages correct, and if yes, what is
    an alternative solution to achieve my goal?

    Thanks for reading this far,
    H.
    - --
    Hendrik Maryns
    http://tcl.sfs.uni-tuebingen.de/~hendrik/
    ==================
    http://aouw.org
    Ask smart questions, get good answers:
    http://www.catb.org/~esr/faqs/smart-questions.html
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.2 (GNU/Linux)

    iD8DBQFFo3uqe+7xMGD3itQRAnkwAJ9Xh23/TQmfIAG4KHZ5wl+Xw8929QCdGE+g
    8A4rE7vVIbTFukegB9VPdt8=
    =AMcn
    -----END PGP SIGNATURE-----
    Hendrik Maryns, Jan 9, 2007
    #1
    1. Advertising

  2. Hendrik Maryns

    Hemal Pandya Guest

    Hendrik Maryns wrote:
    > -----BEGIN PGP SIGNED MESSAGE-----
    > Hash: SHA1
    >
    > Hi,
    >
    > I have a complicated question about overloading with generic arguments.


    Not sure I understand all of this, but I get a similar error when I try
    the following, which is perhaps a SSCCE of your code:

    import java.util.Set;
    class Node {}
    class BidiNode extends Node {}

    class X
    {
    X(Set<Node> r) {}
    X(Set<BidiNode> r) {}
    }

    The error I get with Sun javac is: name clash: X(java.util.Set<Node>)
    and X(java.util.Set<BidiNode>) have the same erasure

    The following equivalent example does not have the compile error. Does
    it solve your problem? Of course, it is a lot more verbose.

    import java.util.Set;
    class Node {}
    class BidiNode extends Node {}

    interface NodeSet extends Set<Node> {}
    interface BidiNodeSet extends Set<BidiNode> {}

    class X
    {
    X(NodeSet r) {}
    X(BidiNodeSet r) {}

    static class ABC extends java.util.HashSet<Node> implements NodeSet
    {}
    static void foo()
    {
    ABC abc = new ABC();
    abc.add(new Node());
    new X(abc);
    }
    }
    Hemal Pandya, Jan 9, 2007
    #2
    1. Advertising

  3. Hendrik Maryns

    Daniel Pitts Guest

    Hemal Pandya wrote:
    > Hendrik Maryns wrote:
    > > -----BEGIN PGP SIGNED MESSAGE-----
    > > Hash: SHA1
    > >
    > > Hi,
    > >
    > > I have a complicated question about overloading with generic arguments.

    >
    > Not sure I understand all of this, but I get a similar error when I try
    > the following, which is perhaps a SSCCE of your code:



    The problem is that
    public void something(Set<A> blah);
    has the same signature as
    public void something(Set<B> blah);
    and also has the same signature as
    public void something(Set blah);

    because of erasure.

    You have a couple of ways to solve your problem.
    1. Use polymorphism of Node and move the differening behaviour from
    your constructor to the Node itself. This is what I would recommend
    based on what I've seen. That way you could have a Set<Node> which
    contains BOTH Bidi nodes and otherwise.
    You could also:
    2. Have a different class that handles your other type of object.
    3. Use Set<? extends Node> so that you have one constructor that takes
    bother types of sets.
    4. Have a different signature for the second type of constructor (add a
    throw-away int)
    Daniel Pitts, Jan 10, 2007
    #3
  4. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    Daniel Pitts schreef:
    > Hemal Pandya wrote:
    >> Hendrik Maryns wrote:
    >>> -----BEGIN PGP SIGNED MESSAGE-----
    >>> Hash: SHA1
    >>>
    >>> Hi,
    >>>
    >>> I have a complicated question about overloading with generic arguments.

    >> Not sure I understand all of this, but I get a similar error when I try
    >> the following, which is perhaps a SSCCE of your code:

    >
    >
    > The problem is that
    > public void something(Set<A> blah);
    > has the same signature as
    > public void something(Set<B> blah);
    > and also has the same signature as
    > public void something(Set blah);
    >
    > because of erasure.


    Yes, but I thought that which overloaded method to choose was decided at
    compile time. Since the compiler knows about generics, it should not be
    a problem.

    > You have a couple of ways to solve your problem.
    > 1. Use polymorphism of Node and move the differening behaviour from
    > your constructor to the Node itself. This is what I would recommend
    > based on what I've seen. That way you could have a Set<Node> which
    > contains BOTH Bidi nodes and otherwise.


    This would of course be the most elegant solution. The problem is: The
    whole purpose of the Node class is to forget about the bidirectional
    stuff. I.e. I have a FunctionBuilder, which needs up pointers, but once
    the function has been built, I want to forget them, to save place.
    Then, the functions are manipulated in ways that only use down pointers.
    So I don’t want to clutter the Function class with anything related to
    the bidirectional pointers. Ideally, I would even remove that
    constructor, which I will probably do, eventually.

    I could make BidiNode extend Node, but then I would have to introduce a
    function in Node that is used in the constructor, which is overridden in
    BidiNode. I do not want that function.

    I think I’ll work with the design some more, and see if something nicer
    comes out of it. I suspect that eventually, I will not need the
    bidirectional nodes anymore, so then the problem solves itself.

    I mainly posed the question out of curiosity why this error occurs.
    Which still is not entirely clear, see above.

    > You could also:
    > 2. Have a different class that handles your other type of object.


    I do not understand.

    > 3. Use Set<? extends Node> so that you have one constructor that takes
    > bother types of sets.


    That would once again require BidiNode to extend Node.

    > 4. Have a different signature for the second type of constructor (add a
    > throw-away int)


    Indeed, but *yuk*. :-(

    H.
    - --
    Hendrik Maryns
    http://tcl.sfs.uni-tuebingen.de/~hendrik/
    ==================
    http://aouw.org
    Ask smart questions, get good answers:
    http://www.catb.org/~esr/faqs/smart-questions.html
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.2 (GNU/Linux)

    iD8DBQFFpMVre+7xMGD3itQRAkTbAJ9ss+IhsfakjfISYJt6eJGQvjsIMwCdEil7
    qCjN6OePkiks0A4DdVORIyw=
    =tTqd
    -----END PGP SIGNATURE-----
    Hendrik Maryns, Jan 10, 2007
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Murat Tasan
    Replies:
    1
    Views:
    8,009
    Chaitanya
    Feb 3, 2009
  2. Replies:
    2
    Views:
    407
  3. Iyer, Prasad C

    Overloading __init__ & Function overloading

    Iyer, Prasad C, Sep 30, 2005, in forum: Python
    Replies:
    3
    Views:
    6,392
    Fredrik Lundh
    Sep 30, 2005
  4. minlearn
    Replies:
    2
    Views:
    436
    red floyd
    Mar 13, 2009
  5. Replies:
    2
    Views:
    774
Loading...

Share This Page