Results 1 to 3 of 3
  1. #1
    Stravant is offline Member
    Join Date
    Dec 2009
    Posts
    3
    Rep Power
    0

    Default Usually work with C++, need help replacing multiple inheritance in this case

    I usually work with C++ (I would call myself "experienced" with it), and I'm just starting out with Java. To start out, I'm working on porting a set of simple classes that I use for making quick 2D games with, but I can't figure out how to replace the multiple inheritance that I used in the C++ version's event handling system. Here's the basic layout of my code:
    Java Code:
    //class from which all GuiObjects are derived
    public class GuiObject {
    //overridden by inheriting object, called when any event pertaining to the Gui fires
    protected void classEvent(...) {
    
    }
    }
    
    //an example interface, which defines certain event handler functions
    public interface GuiMouseButtonEvent {
    //overrides the classevent, and calls on this handlers functions
    protected void classEvent(...); //IN C++ I WOULD DEFINE IT HERE
    protected void OnButtonDown();
    protected void OnButtonUp();
    ...
    }
    
    public class TestObject extends GuiObject implements GuiMouseButtonEvent {
    protected void classEvent(...) { //PROBLEM!! --> THE USER SHOULD NOT HAVE TO DEFINE THIS, WHERE / HOW SHOULD I DEFINE IT?
    
    }
    protected void OnButtonDown() {
    
    }
    protected OnButtonUp() {
    
    }
    }
    GuiObject is the superclass from which all derived. The idea is that a class should inherit from GuiObject, and if it wants events, it should implement the even interfaces for the events that it wants.

    The problem is that the GuiObject class should not be aware of any of the event interfaces. Where do I implement each interface's code for determining what handlers(s) to call on given the event? Given that the user should not see that code, and the GuiObject class cannot be aware of each event's implementation?

    I don't necessarily need to keep it this way, so if I'm simply taking the wrong approach altogether, then please let me know, thanks.

    -Stravant

  2. #2
    travishein's Avatar
    travishein is offline Senior Member
    Join Date
    Sep 2009
    Location
    Canada
    Posts
    684
    Rep Power
    5

    Default

    yes, thats a good example of why multiple inheritence can be a good thing, but i digress, that discussion is long dead for why Java doesn't do it.

    I sometimes create intermediate Glue objects that extend my parent class and provide default implementations of the methods. In your case,

    Java Code:
    public class MyDefaultMouseButtonEvent extends GuiObject implements GuiMouseButtonEvent {
    protected void classEvent(...) { // implement it here
    
    }
    
    
    public class TestObject extends MyDefaultMouseButtonEvent 
    //implements GuiMouseButtonEvent 
    {
    and in a general case, if I have a BaseClass, for which I want all my objects to extend,
    and I have interfaces A, B, C, and I want some classes to implement {A}, {B}, {C}, {A,B}, {B,C}, {A,C}, {A,B,C}, then yes, I need to make like 7 of these glue classes, where yes, possibly I would have to implement the method bodies more than once. But in this case I work around this by creating a static utility method, or some other spot for which I can have the method in the glue class(es) that needss to be there just to satisfy the implementation of the interface requirement,

    Java Code:
    GuiMouseButtonEvent {
    protected void classEvent(...) { // implement it here
      GUIUtils.classEvent(); // our function just calls our single defined logic somewhere else
    }
    but that shouldn't be a problem in your case, you want to not require the user to need to do this implement a method thing in their class at all.

    Another idea, would it be possible to reverse the interface / class. what does GUIDObject contain ?

    In some cases if the base class is really behaving more like a 'marker', then I have been able to make the 'interface classeses and the classes interfaces'.

    For example, instead of having BaseObject class that I extend and interfaces A, B, C,
    if I create ClassA and implement some BaseInterface instead.

    Oh, and another thing that comes in handy sometimes, which I guess is closer to multiple inheritence, is containership, where your class defines a member (field) that is an instance of the other class that used to be inheriting from.

    For example,
    Java Code:
    public class GuiMouseButtonEvent {
    protected void classEvent(...) { 
    
    }
    protected void OnButtonDown() {
    
    }
    protected OnButtonUp() {
    
    }
    }
    
    public class TestObject extends GuiObject {
      GuiMouseButtonEvent mymouseListenerInstance;
    }
    Though this can be more fun to initialize, where the internal member needs to be set, like in a constructor [argument]. and it needs to know how to get a handle on this object that is owning the reference, and our object would need to invoke it.

    Sometimes the best solution is to not try to 1:1 map the C++ object, but to try to use the Java-esq facilities that already exist for solving a problem. For example, in a JButton (a component in the Swing API), it is sometimes convenient to have it's event handler implemented inline by an anonymous inner class

    Java Code:
      JButton okButton = new JButton("OK");
    
      okButton.addActionListener(
        new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          // here the logic of when the button would be pressed, can access things in the parent java class, or propertis in this code block parent if they are final.
        }
      });
    where this creates a new anonymous instance of an Interface, which we can do if we supply the methods required for its existence as we do here inline like this. - in general you can create special subclassed instances of any object in java like this and override just one method and such.

    but in a more practical sense, when there would be more than one button using things, and in your case, a mouse listener,

    Java Code:
      MouseListener myMouseListener = new MouseAdapter() {
       // MouseAdapter is a built-in thing that just implements the MouseListener interface,
      // here you would provide method implementations for the event things you care about.
      }
    
      JButton okButton = new JButton("OK");
      okButton.addMouseListener(myMouseListener);
    
      JButton cancelButton = new JButton("Cancel");
      cancelButton.addMouseListener(myMouseListener);
    The idea here is the MyTestObject that extends the GuiObject, no longer needs to also extend implement the mouse listener interface,. instead is getting around it by the use of containership of the handler, where her we did it as an anonymous inner class instance, but it could very well be a real class or a concrete inner class.

  3. #3
    Stravant is offline Member
    Join Date
    Dec 2009
    Posts
    3
    Rep Power
    0

    Default

    "Another idea, would it be possible to reverse the interface / class. what does GUIDObject contain ?"
    Interesting idea, but that would be even more so of a problem. GuiObject itself is a fairly heavy object (should have described what else it has in the first place, sorry). It contains a parent-child object hierarchy, and a bunch of layout and rendering functionality, events are by far the smallest part of the implementation done in the class.

    "it is sometimes convenient to have it's event handler implemented inline by an anonymous inner class"
    While I was reading what you had to say about that it finally clicked a way I could implement that, I was having trouble figuring how exactly that worked internally before.

    Here's the new idea, it's looking like it should work:
    Java Code:
    public class GuiEventH {
    protected void Implementation(...) {
    //overridden by each type of event handler, calls handlers of that event class
    
    }
    }
    
    public class GuiObject {
    //handlers
    private GuiEventH[] handlers; //array for now
    protected void HandleEvent(...) {
    //default behavior is to call on handlers 
    for (GuiEventH handler : handlers) {
    hander.Implimentation(...);
    }
    }
    protected void AddHandler(GuiEventH h) {
    whatever_the_table_insert_function_is(handlers, h);
    }
    }
    
    public class GuiMouseButtonEventH() {
    protected void Implementation(... e) {
    if (e instanceof buttonevent) {
    OnClick();
    }
    }
    void OnClick() {
    
    }
    }
    
    public class TestButton extends GuiObject {
    TestButton() {
    AddHandler(new GuiMouseButtonEventH() {
    void OnClick() {
    Remove(); //remove self, easy to test
    }
    })
    }
    }
    Thanks for you help.

Similar Threads

  1. subclasses and inheritance - how's it all work?
    By 711groove in forum New To Java
    Replies: 14
    Last Post: 12-18-2009, 09:04 AM
  2. SashForm doesn't seem to work in this case
    By Rodrigo Braz in forum SWT / JFace
    Replies: 0
    Last Post: 03-22-2009, 10:39 AM
  3. multiple inheritance in java
    By pawanspace in forum New To Java
    Replies: 2
    Last Post: 12-31-2007, 04:08 AM
  4. Multiple Inheritance
    By mew in forum New To Java
    Replies: 1
    Last Post: 12-01-2007, 10:04 PM
  5. Multiple Inheritance in java
    By paty in forum New To Java
    Replies: 4
    Last Post: 08-02-2007, 02:25 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •