I'm trying to create a generic boradcaster to which client code may subscribe. Client code will then be updated (via the ReportListener) when any changes are mode to concrete Reporter_Abstract sub classes.
I know I'm over using generics here (for example
public abstract class Reporter_Abstract<I extends Reporter_Abstract<I>>
feels dirty), but i'm not sure how to enforce these requirements in another way. How can i ensure that a listener added in code handles changes to I, where I is the subtype of Reporter_Abstract
public abstract class Reporter_Abstract<I extends Reporter_Abstract<I>>
{
private final List<ReportListener<I>> _listeners;
/**
* Broadcast change to any attached listeners, skipping the sender
*/
protected final void reportChange( ReportListener<I> sender )
{
List<ReportListener<I>> listeners = collectListeners();
for( ReportListener<I> listener : listeners )
{
try
{
if( sender == null || sender != listener )
{
listener.recognizeChange( (I) this );
}
}
catch( Exception e )
{
_log.error( "Uncaught exception from listener: " + listener, e );
}
}
}
}
public class SomeStateReporter extends Reporter_Abstract<SomeStateReporter>
{
private boolean _isSomeStateActive;
public void setSomeStateActive( boolean isSomeStateActive )
{
if( isSomeStateActive ^ _isSomeStateActive )
{
_isASomeStateActive = isSomeStateActive;
super.reportChange();
}
}
}
public interface ReportListener<T extends Reporter_Abstract<?>>
{
public void recognizeChange( T report );
}
And the class that wants to listen to changes
public class ChangeHandlingClass()
{
public void attachSomeStateListener( SomeStateReporter someStateReporter )
{
sometateReporter.addListener( new SomeStateUpdateListener() );
}
private class SomeStateUpdateListener implements ReportListener<SomeStateReporter>
{
@Override
public void recognizeChange( SomeStateReporter report )
{
handleStateChange( report.isSomeStateActive()
}
}
}
If this is the right way (or A right way), then shouldn't this line
listener.recognizeChange( (I) this );
allow me to use an argument of 'this' without the cast, and know that this is the definition of I?
Am I way off base?