Why is firePropertyChange(String propertyName, Object oldValue, Object newValue) protected and not public?

dic19 picture dic19 · Jan 10, 2014 · Viewed 10.8k times · Source

Well the thing is I'm working on a IDateEditor interface implementation from JCalendar library and I've noticed that Component.firePropertyChange(String propertyName, Object oldValue, Object newValue) method is not public but protected. The situation is illustrated below:

public class DateFormattedTextField implements IDateEditor {

    private JFormattedTextField editor;        
    private DateUtil dateUtil;

    ...

    @Override
    public void setDate(Date date) {
        Date oldDate = (Date)editor.getValue();            
        if(dateUtil.checkDate(date)){
            editor.setValue(date);
            editor.firePropertyChange("date", oldDate, date); // <-- error here
        }
    }

}

As you can see I'm not able to fire a property change because of this method being protected. Of course if I make my class extending from JFormattedTextfield instead of using a simple variable I could easily get rid of this problem.

public class DateFormattedTextField extends JFormattedTextField implements IDateEditor {

    private DateUtil dateUtil;

    ...

    @Override
    public void setDate(Date date) {
        Date oldDate = (Date)getValue();            
        if(dateUtil.checkDate(date)){
            setValue(date);
            firePropertyChange("date", oldDate, date); // <-- No problem here
        }
    }
}

But that's not what I'm asking. I would like to know: why is this method protected?

I know it should be some design matter but I can't figure out why is that, especially considering that most of methods to fire property change events are public:

enter image description here

Maybe most experienced developers can shed some light on this. Thanks in advance.

Addendum:

Here is my code so far. Feel free to use/modify/play-with it.

public class DateFormattedTextField implements IDateEditor {

    private JFormattedTextField editor;        
    private DateUtil dateUtil;
    private DateFormat dateFormat;
    private String dateFormatString;

    public DateFormattedTextField(){
        dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM);
        editor = new JFormattedTextField(dateFormat);
        editor.setColumns(10);
        editor.setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT);
        dateUtil = new DateUtil();            
    }

    @Override
    public Date getDate() {
        return (Date)editor.getValue();
    }

    @Override
    public void setDate(Date date) {
        Date oldDate = (Date)editor.getValue();            
        if(dateUtil.checkDate(date)){
            editor.setValue(date);
            editor.firePropertyChange("date", oldDate, date); // <-- error here
        }
    }

    @Override
    public void setDateFormatString(String dateFormatString) {
        this.dateFormatString = dateFormatString;
    }

    @Override
    public String getDateFormatString() {
        return this.dateFormatString;
    }

    @Override
    public void setSelectableDateRange(Date min, Date max) {
        dateUtil.setSelectableDateRange(min, max);
    }

    @Override
    public Date getMaxSelectableDate() {
        return dateUtil.getMaxSelectableDate();
    }

    @Override
    public Date getMinSelectableDate() {
        return dateUtil.getMinSelectableDate();
    }

    @Override
    public void setMaxSelectableDate(Date max) {
        dateUtil.setMaxSelectableDate(max);
    }

    @Override
    public void setMinSelectableDate(Date min) {
        dateUtil.setMinSelectableDate(min);
    }

    @Override
    public JComponent getUiComponent() {
        return editor;
    }

    @Override
    public void setLocale(Locale locale) {
        editor.setLocale(locale); // to be reviewed
    }

    @Override
    public void setEnabled(boolean enabled) {
        editor.setEnabled(enabled);
    }

    @Override
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        editor.addPropertyChangeListener(listener);
    }

    @Override
    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        editor.addPropertyChangeListener(propertyName, listener);
    }

    @Override
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        editor.removePropertyChangeListener(listener);
    }

    @Override
    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        editor.removePropertyChangeListener(propertyName, listener);
    }
}

Answer

kleopatra picture kleopatra · Jan 10, 2014

Change notification is the inherent responsibility of any observable (in general and a java bean in particular): it would violate its contract if it wouldn't fire a PropertyChangeEvent when any of its bound properties is changed. That being the case, no other party ever needs to use the fireXX methods.

So it simply doesn't make any sense to have a scope wider than protected. If you feel like needing it, you are doing something wrong.