begin  quoting Wade Curry as of Sat, Jun 16, 2007 at 01:03:18PM -0700:
> Stewart Stremler([EMAIL PROTECTED])@Sun, Jun 10, 2007 at 12:28:34AM -0700 
> wrote:
> > All I wanted was covariant return types.
>  
> Ah.  Now, when I know what generics are, maybe I'll understand
> explanations of "raw collections" and "covariant return types" :-)
> Oh, and synchronize.
> 
> If anyone is willing to instruct, please do!

Given a class hierarchy for are types:

class Foo { ... }
class Bar extends Foo { ... }
class Baz extends Bar { ... }

We can talk about another hiearchy that uses those types:

class P {
  void someMethod( Bar b) { ... }
}

class Q extends P { 
  void someMethod( Bar b) { ... }
}

Because Q subclasses P, Q can override the "someMethod" method. But
we don't /have/ to keep the argument type the same. We can do:

class Q extends P { 
  void someMethod( Foo f ) { ... }
}

Since every object of type Bar is *also* of type Foo, we can "widen"
the type. Code that has a variable of type P can treat objects of type
Q as if they were of type P, because every argument they can provide
to P would work with Q.

One would /expect/ that something analogous could be done with return types:

class M {
   Bar anotherMethod() { ... }
}

class N extends M {
   Baz anotherMethod() { ... }
}

*This* is called "covariant return types". Objects of type Baz are also
of type Bar, so code that has a variable of type M and expect to get
back an object of type Bar won't be upset if they get back an object
of type Baz.

....

Many OO languages provide "container classes". These are libraries of
common data structures so that the programmer doesn't have to
reimplement (and retest) basic code. Generally, they're lists, maps,
trees, and suchlike.

Java calles these things "Collections", as they are various means of
"collecting" objects.

A "raw collection" is just one of the Collection classes that takes
Object. For example, a Vector. A Vector is a simple unsorted ordered
list of Objects.

If I choose to either compose or extend the Vector so that it will only
hold objects of a particular type, it's specialized. Otherwise, I refer
to it as a "raw" Vector.

Generics, in Java, provide a quicky and easy way of makeing a specialized
collection... so instead of having just a Vector (of objects), or
writing code like this:

public class MyVector {
   private Vector vector;
   public MyObject get( int i ) { return (MyObject) vector.get( i ); }
    ...
}

Or like this:

public class MyVector extends Vector {
   public Object get( int i ) { return (MyObject) super.get( i ); }
   ...
}

...or with covariant return types:

public class MyVector extends Vector {
   public MyObject get( int i ) { return (MyObject) super.get( i ); }
   ...
}

I can write

Vector<MyObject> vector;

...and be done. Very nice. Up to a point. And then it gets ugly and
suprising rather fast. Up to that point, it saves on a ton of code.

Better?

[Assuming I haven't made any stupid mistakes, which I'm sure will be
called out in no time at all by the peanut gallery.]

> > But now I read that you're not supposed to use those... Wah!
> 
> They probably figure that if you're using those, you must be
> writing poor OO code anyway.  So, why worry about it?  ;-D
 
Phhhhbt!

The explanations given have been kind of spurious, it seems to me.

If Programmer A extends my class M and provides an implementation of
anotherMethod() that returns Bar, they can't easily change that to
subclass N instead of M.

-- 
This sort of thing doesn't happen often in my experience.
Stewart Stremler

-- 
[email protected]
http://www.kernel-panic.org/cgi-bin/mailman/listinfo/kplug-lpsg

Reply via email to