0

I'm creating a class that extends PropertyChangeSupport. What I currently want to do is override firePropertyChange():

firePropertyChange as it is implemented in PropertyChangeSupport:

public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
    if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
        firePropertyChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
    }
}

my intended override of firePropertyChange:

public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
    if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
        firePropertyChange(new JoystickPropertyChangeEvent(this.source, propertyName, oldValue, newValue)); //compile error: source is not visible
    }
}

JoystickPropertyChangeEvent is a class that I created and that extends ProperyChangeEvent.

The problem is that my intended implementation does not compile because source is private and has no getters in PropertyChangeSupport, so subclasses have no access to it. I cannot modify PropertyChangeSupport's code.

Is there a more elegant way of solving this than having a private copy of source as a field of my subclass?

Related question: How to access the private variables of a class in its subclass?

Community
  • 1
  • 1
deinocheirus
  • 1,833
  • 5
  • 26
  • 44

5 Answers5

2

Since you extend PropertyChangeSupport you are calling super() in constructor correct? The original constructor of PropertyChangeSupport takes the source (i.e. a bean) as an argument.

public PropertyChangeSupport(Object sourceBean).

The sourceBean argument is the source you want. Use your own private member to save that reference. Then you could use it inside the firePropertyChange() method.

public static class MyPropertyChangeSupport extends PropertyChangeSupport {
    private Object mySource;

    public MyPropertyChangeSupport(Object sourceBean) {
        super(sourceBean);
        // store the bean reference in your field
        this.mySource = sourceBean;
    }

    @Override
    public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
        if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
            // use mySource here
            firePropertyChange(new JoystickPropertyChangeEvent(mySource, propertyName, oldValue, newValue)); 
        }
    }
}
c.s.
  • 4,786
  • 18
  • 32
  • "Use your own private member to save that reference." is exactly what I wanted to avoid if possible. – deinocheirus Jul 25 '13 at 13:16
  • You can't avoid it if you want to use it. Any other approach i.e. reflection will just mess up your class. Do you have a specific reason you want to avoid it? – c.s. Jul 25 '13 at 13:34
1

I would question the design of this.

The method that you are trying to override has been made private for a reason, even if you could change its implementation I wouldn't advise it since you don't know what impact this will have elsewhere.

StuPointerException
  • 7,117
  • 5
  • 29
  • 54
1

If you were really stupid, you might try to solve this problem with reflection. But that's so complicated I won't even mention it again.

It seems like your goal is to have property change listeners be able to tell some events apart from other events. If the listeners can tell them apart without help, just do that. If that's inconvenient, provide a static method to ananlyze a property change event and return whether it should have been a JoystickPropertyChangeEvent.

Also, why should you use property change events at all? If you want to fire an event when the state of the joystick updates, you should fire your own custom event for that.

tbodt
  • 16,609
  • 6
  • 58
  • 83
0

You can use reflection for this purpose.

If ParentClass private variable is like

private String private_source_parent = "some_value";

inside your ChildClass which extending parent class

ParentClass obj = new ParentClasS();
Field f = obj.getClass().getDeclaredField("private_source_parent"); //NoSuchFieldException
f.setAccessible(true);
String source_inchild = (String) f.get(obj);

Here in your ChildClass you will get the value of parent private member.

Niju
  • 487
  • 1
  • 9
  • 18
  • 2
    That's a horrible hack that you should only do if there really is no other way to solve the problem. – Jesper Jul 25 '13 at 12:27
  • Without this hack is there any other way to access private data member of parent class that without getter method in child class? – Niju Jul 25 '13 at 12:40
  • Probably not. But the solution to the problem that deinocheirus has is to refactor his code so that this isn't necessary, instead of hacking his way in. – Jesper Jul 25 '13 at 12:48
-1

You could use the getter-method of your superclass to get the source property i.e.

super.firePropertyChange(new JoyStickPropertyChangeEvent(super.getSource, propertyName, oldValue, newValue); 

This should do the trick. As explanation you have to call the firePropertyChange method of the super class explicit. This is done with the keyword super.

Hope this helps

Cheers

ZeusNet
  • 710
  • 9
  • 25
  • This calls the method but doesn't change its implementation. Calls to public void firePropertyChange(String propertyName, Object oldValue, Object newValue); still result in the wrong method being called. – StuPointerException Jul 25 '13 at 12:01
  • I can't see in the documentation that this method is declared as private? `public void firePropertyChange(PropertyChangeEvent evt)` according to [http://docs.oracle.com/javase/6/docs/api/java/beans/PropertyChangeSupport.html#firePropertyChange(java.beans.PropertyChangeEvent)](link). Maybe the getSource-Method of the superclass is private but then he should implement this method by his own. – ZeusNet Jul 25 '13 at 12:06