如何解决这个java泛型过度使用或滥用

时间:2011-09-19 19:09:11

标签: java generics inheritance

我正在尝试创建一个客户端代码可以订阅的通用boradcaster。当任何更改是具体的Reporter_Abstract子类的模式时,客户端代码将被更新(通过ReportListener)。

我知道我在这里使用泛型(例如

public abstract class Reporter_Abstract<I extends Reporter_Abstract<I>>

感觉很脏),但我不确定如何以另一种方式强制执行这些要求。如何确保在代码中添加的侦听器处理对I的更改,其中I是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 );
}   

想要听的课程改变

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()
        }
  }
}

如果这是正确的方式(或正确的方式),那么不应该这一行

listener.recognizeChange( (I) this );

允许我在没有演员的情况下使用'this'的参数,并且知道这是我的定义吗?

我离开基地了吗?

3 个答案:

答案 0 :(得分:3)

@StriplingWarrior我在这篇文章中讨论了类似的模式:Is there a way to refer to the current type with a type variable?

我想说你在实现这种模式方面并没有偏离轨道,但重要的是要认识到Reporter_Abstract必须为其子类布局的合同,这些子类负责正确实现它。只要子类使用具有自己类型的类型参数final,子类必须为I,以防止其他子类使I不正确。

Enum采用了类似的模式 - 这是enum无法扩展的另一个原因,因为其父类Enum期望其类型参数E与延伸enum

真正的问题是你是否想要这种模式,而不是@Andy suggests。如果您对Reporter_Abstract的任何子类进行独占控制,那么您尝试做的事情只能安全地完成。

答案 1 :(得分:3)

  

如果这是正确的方式(或正确的方式),那么不应该这一行

listener.recognizeChange( (I) this );
     

允许我在没有演员的情况下使用'this'的参数,并且知道这是我的定义吗?

因为有人可能会声明:

class MyEvilReporter extends Reporter_Abstract<SomeStateReporter> {
    ...
}

至于解决问题,你不能这样做:

interface ChangeListener {
    void stateChanged();
}

根据我的经验,听众经常知道他们在听什么,所以不需要这个方法参数,因此不需要与泛型作斗争: - )

答案 2 :(得分:2)

  

如何确保在代码中添加的侦听器处理对I ...

的更改

在多个代码库中,对我有用的一种模式是,不是根据发件人定义侦听器,而是根据发件人发送的事件来定义。这允许与通知一起发送数据,包括对发件人的引用。

此模式有效:

// Listener type
public interface IEventListener<EVENT> {
    public void receiveEvent( @NonNull EVENT event );
}

// Event producer interface
public interface IEventProducer<LISTENER extends IEventListener<EVENT>, EVENT> {
    public void addEventListener( @NonNull LISTENER listener );
    public void removeEventListener( @NonNull LISTENER listener );
}

// Concrete implementation
public final class EventProducer<LISTENER extends IEventListener<EVENT>,EVENT> 
  implements IEventProducer<LISTENER, EVENT> { ... }

如果侦听器实际上是发件人,则可以跳过自己。请注意,某些侦听器可能是发件人的内部类。

请注意,生成器实现按组合而不是继承包含在发件人中,这使得它甚至可以在已经拥有超类的类中使用。