Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / May 2007

Tip: Looking for answers? Try searching our database.

Workaround to overcome the generics limitation causes by Erasure

Thread view: 
yancheng.cheok@gmail.com - 02 May 2007 14:23 GMT
Initially, I thought the introduce of generics in Java would solve me
some problem in pattern design. Here, I make use of generic to design
Observer/Subject pattern.

public interface Observer<S, A> {
   public void update(S subject, A arg);

}

public class Subject<S, A> {

   public void attach(Observer<S, A> observer) {
       observers.add(observer);
   }

   void notify(S subject, A arg) {
       for (Observer<S, A> obs : observers) {
           obs.update(subject, arg);
       }
   }

   private List<Observer<S, A>> observers = new
CopyOnWriteArrayList<Observer<S, A>>();

}

However, due to the limitation of generics causes by erasure, I am
unable to have two different instantiations with same generics
interface

http://angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#Can%20a
%20class%20implement%20different%20instantiations%20of%20the%20same%20parameteri
zed%20interface
?

Compiler will complain if I tend to make an Object act as more than
one type of Observer.

public class MainFrame extends javax.swing.JFrame implements
org.yccheok.jstock.engine.Observer<RealTimeStockMonitor,
java.util.List<org.yccheok.jstock.engine.Stock>>,
org.yccheok.jstock.engine.Observer<StockHistoryMonitor,
StockHistoryServer>

Currently, my workaround for this is using

public class MainFrame extends javax.swing.JFrame implements
org.yccheok.jstock.engine.Observer<Object, Object>

and performing instanceof checking (to check whether it is
RealTimeStockMonitor or StockHistoryMonitor) during runtime.

I had gone through severals articles :

http://www-128.ibm.com/developerworks/java/library/j-jtp01255.html
http://gafter.blogspot.com/2004/09/puzzling-through-erasure-answer.html
http://gafter.blogspot.com/2006/11/reified-generics-for-java.html

Till now, I still do not have any better workaround, in order to have
a typed-safe Observer/ Subject pattern. Can anyone of you share your
experience, how do you overcome this situation?

Thank you very much!
Daniel Pitts - 02 May 2007 15:50 GMT
On May 2, 6:23 am, yancheng.ch...@gmail.com wrote:
> Initially, I thought the introduce of generics in Java would solve me
> some problem in pattern design. Here, I make use of generic to design
[quoted text clipped - 54 lines]
>
> Thank you very much!

public interface Observer<S, A> {
    void update(S subject, A arg);
}

Where does the compiler complain about here:

class MyObserver {
  public void update(Foo subject, Integer arg) {
  }

  public void update(Bar subject, String arg) {
  }

  public Observer<Foo, Integer> getFooObserver() {
     return new Observer<Foo, Integer>() {
       public void update(Foo subject, Integer arg) {
         MyObserver.this.update(subject, arg);
       }
  }
  public Observer<Bar, Integer> getBarObserver() {
     return new Observer<Bar, Integer>() {
       public void update(Bar subject, Integer arg) {
         MyObserver.this.update(subject, arg);
       }
  }
}

Hope this helps,
Daniel.
Hendrik Maryns - 02 May 2007 16:20 GMT
yancheng.cheok@gmail.com schreef:
> Initially, I thought the introduce of generics in Java would solve me
> some problem in pattern design. Here, I make use of generic to design
[quoted text clipped - 6 lines]
>
> public class Subject<S, A> {

Have you thought about why you have the S parameter here?  I have the
intuition it is unnecessary: it is Subject itself right?

>     public void attach(Observer<S, A> observer) {
>         observers.add(observer);
[quoted text clipped - 19 lines]
> Compiler will complain if I tend to make an Object act as more than
> one type of Observer.

Of course.  Imagine one extends implements List<Integer> and
List<String> at the same time.  That doesn’t make sense.

> public class MainFrame extends javax.swing.JFrame implements
> org.yccheok.jstock.engine.Observer<RealTimeStockMonitor,
[quoted text clipped - 9 lines]
> and performing instanceof checking (to check whether it is
> RealTimeStockMonitor or StockHistoryMonitor) during runtime.

Why don’t you just have two observers, each doing its function?  You
have a method addObserver(Observer) right?

Please show some more code, i.e. not only the definition of the
interfaces/classes above, but also how you use them.

In general, every time someone complains about erasure, it is because
they have a flaw in their design.

H.
- --
Hendrik Maryns
http://tcl.sfs.uni-tuebingen.de/~hendrik/
==================
http://aouw.org
Ask smart questions, get good answers:
http://www.catb.org/~esr/faqs/smart-questions.html
yancheng.cheok@gmail.com - 02 May 2007 17:21 GMT
>>> Have you thought about why you have the S parameter here?  I have the
intuition it is unnecessary: it is Subject itself right?

public void update(S subject, A arg);

After the observer receive notification from subject, it may need to
access the properties of the subject, in order to get the detail of
the notification message. Yes! we may pass along the notification
message by using the arg. However, this require us to design another
class, just to carry out the notification message. Please see my
sample code in detail later.

>>> Why don't you just have two observers, each doing its function?  You
have a method addObserver(Observer) right?

Most of the situation, a single observer need to respond to multiple
subjects.

For more detailed explanation, please refer to a C++ version

http://www.codeproject.com/cpp/observer_with_templates.asp

Here is my sample code.

GUIToDisplayTimeAndTemperature is a GUI application. It will receive
notification from MyTemperature and MyTime, whenever there is a
temperature change or time change. Once it receive the notification,
it will access the properties of MyTemperature and MyTime, and update
the GUI display accordingly, using those subject's properties.

Please note that the following code won't compile, due to Erasure

/*** MyTemperature.java ***/
public class MyTemperature extends Subject<MyTemperature, String> {

   /** Creates a new instance of MyTemperature */
   public MyTemperature() {
   }

   public void run() {
       System.out.println("MyTemperature is doing some time consuming
calculation...");
       result = 980;
       System.out.println("MyTemperature calculation is done. Going
to notify all the observers");

       notify(this, "Some Extra Arguement from MyTime");
   }

   public int getTemperature() {
       return result;
   }

   private int result = 0;
}

/*** MyTime.java ***/
public class MyTime extends Subject<MyTime, String> {

   /** Creates a new instance of MyTime */
   public MyTime() {
   }

   public void run() {
       System.out.println("MyTime is doing some time consuming
calculation...");
       result = 100;
       System.out.println("MyTime calculation is done. Going to
notify all the observers");

       notify(this, "Some Extra Arguement from MyTime");
   }

   public int getTime() {
       return result;
   }

   private int result = 0;
}

/*** GUIToDisplayTimeAndTemperature.java ***/

public class GUIToDisplayTimeAndTemperature implements
Observer<MyTemperature, String>, Observer<MyTime, String> {

   /** Creates a new instance of Main */
   public GUIToDisplayTimeAndTemperature() {
       MyTemperature temperature = new MyTemperature();
       MyTime time = new MyTime();

       temperature.attach(this);
       time.attach(this);

       temperature.run();
       time.run();
   }

   public void update(MyTemperature temperature, String arg) {
       System.out.println("GUI : temperature is now " +
temperature.getTemperature());
       System.out.println("GUI : here is the arg from temperature " +
arg);
   }

   public void update(MyTime time, String arg) {
       System.out.println("GUI : time is now " + time.getTime());
       System.out.println("GUI : here is the arg from temperature " +
arg);
   }

   /**
    * @param args the command line arguments
    */
   public static void main(String[] args) {
       // TODO code application logic here
       new GUIToDisplayTimeAndTemperature();
   }

}

However, based on the suggestion from Daniel Pitts, we might have a
workaround.

Although it make more sense (and better clean design) to have
GUIToDisplayTimeAndTemperature itself to be the "observer of
temperature" and "observer of time", instead of having an anonymous
class to take that role.

At least suggestion from Daniel Pitts gives something which work :)
Thanks!

public class GUIToDisplayTimeAndTemperature {
// public class GUIToDisplayTimeAndTemperature {

   /** Creates a new instance of Main */
   public GUIToDisplayTimeAndTemperature() {
       MyTemperature temperature = new MyTemperature();
       MyTime time = new MyTime();

       temperature.attach(getTemperatureObserver());
       time.attach(getTimeObserver());

       temperature.run();
       time.run();
   }

   public Observer<MyTemperature, String> getTemperatureObserver() {
       return new Observer<MyTemperature, String>() {
           public void update(MyTemperature temperature, String arg)
{
               System.out.println("GUI : temperature is now " +
temperature.getTemperature());
               System.out.println("GUI : here is the arg from
temperature " + arg);
           }
       };
   }

   public Observer<MyTime, String> getTimeObserver() {
       return new Observer<MyTime, String>() {
           public void update(MyTime time, String arg) {
               System.out.println("GUI : time is now " +
time.getTime());
               System.out.println("GUI : here is the arg from
temperature " + arg);
           }
       };
   }

   /**
    * @param args the command line arguments
    */
   public static void main(String[] args) {
       // TODO code application logic here
       new GUIToDisplayTimeAndTemperature();
   }

}


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.