On Apr 19, 9:06 pm, Eric <[email protected]> wrote:
> As I've been told, one should not declare parameters to client GWT
> code as interfaces like List<T>.

AFAICT it only applies to things that'll go through GWT-RPC calls
(because you might be sent any implementation of List<T>, GWT has to
generate the code for all known implementation so it can deserialize
them; the more you're explicit the less code it involves: specifying
AbstractList<T> would only generate serialization/deserialization code
for classes that inherit AbstractList<T>, ArrayList<T> only
ArrayList<T> itself (as it's a concrete class) and those that extend
ArrayList<T> and so on)

> The typical way to write a JavaBean
> containing a list is this:
>
> public class Frames {
>    private List<Integer> frames = new ArrayList<Integer>();
>    public void setFrames(List<Integer> frames) {
>     this.frames = frames;
>   }
>   // ...
>
> }
>
> Google recommends that GWT classes use the specific ArrayList<T>
> instead, because these declarations will force GWT to generate code
> for LinkedList<T> and every other implementation of List.
>
> However, this runs into another problem: encapsulation.  The class
> Frames2 is unsafe:
>
> public class Frames2 {
>    private ArrayList<Integer> frames = new ArrayList<Integer>();
>    public void setFrames(ArrayList<Integer> frames) {
>     this.frames = frames;
>   }
>  public ArrayList<Integer> getFrames() {
>     return frames;
>   }
>
> }
>
> It suffers from aliasing, as setting the frames instance variable
> allows the setter to interfere with the internals of the Frames2
> instance:
>
> Frames2 frames = new Frames2();
> ArrayList<Integer> myScoreLine = new ArrayList<Integer>();
> myScoreLien.add(9);
> frames.setFrames(myScoreLine);
> myScoreLine.set(0, 30);  // CHEAT!

I can't tell the difference with your Frame class above:
Frames frames = new Frames();
// using a linked list just to change the scenario a bit
List<Integer> myScoreLine = new LinkedList<Integer>();
myScoreLine.add(9);
frames.setFrames(myScoreLine);
myScoreLine.set(0, 30);  // CHEAT!

And how is it different from this code:
Frames2 frames = new Frames2();
List<Integer> myScoreLine = frames.getFrames();
myScoreLine.add(9);
// ...
myScoreLine.set(0, 30);


> Usually, one copies the lists on both setting and getting:
>
> public class Frames3 {
>    private ArrayList<Integer> frames = new ArrayList<Integer>();
>    public void setFrames(ArrayList<Integer> frames) {
>     this.frames = new ArrayList<Integer>(frames);
>   }
>  public ArrayList<Integer> getFrames() {
>     return new ArrayList<Integer>(frames);
>   }
>
> }
>
> This solves the aliasing problem, but is slow. Perhaps I should not
> vend the list but provide access to its members. I probably should
> provide a way of getting all the list's members at once:
>
> public class Frames4 {
>    private ArrayList<Integer> frames = new ArrayList<Integer>();
>    public void addFrame(int score) {
>     frames.add(score);
>   }
>
>   public Iterator<Intgeer> frames() {
>     return frames.iterator();
>   }
>
> }

How about:
public class Frames5 {
   private ArrayList<Integer> frames = new ArrayList<Integer>();
   public List<Integer> getFrames() {
      return frames;
   }
   // no setter
}
and manipulating the list returned by getFrames() directly?
(see code sample above)

And if you want to add a bunch the frames:
frames.getFrames().addAll(myScoreLine);
eventually preceded by a call to frames.getFrames().clear() if you
want to replace the list. Sure this will be a bit inefficient (just as
if you copied the list on a setter), but at least it's made clear from
the caller's POV.

> Will this force GWT to generate code for every Iterator<E> in my
> system?

No, because GWT-RPC looks at fields, and your field is an
ArrayList<T>.

> I probably am programming with too much paranoia, of course.

Probably yes, moreover if you're not developing a library but an
application, where you control how your classes will be used from end
to end (within your team).

-- 
You received this message because you are subscribed to the Google Groups 
"Google Web Toolkit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-web-toolkit?hl=en.

Reply via email to