Eliminating type parameters used only for superclass information?

I have a class called BaseObject. I have another class called Reference. A

BaseObject has one canonical Reference that can be gotten and set. A Reference

is capable of pointing at a BaseObject subclass of a particular type and can

return the Class of that BaseObject subclass.

I'd like to genericize these classes so that if you create a reference and

assign it to an object, their types should line up. That is, a Reference that

points to a Banana should not be able to be assigned as a canonical reference to

a Cherry.

My goal is to express these type constraints once somewhere. I cannot seem to

achieve my goal.

Pass one, which looks OK at the outset:

publicclass BaseObject<Textends BaseObject>{

public Reference<T> getReference(){

//...

}

publicvoid setReference(final Reference<T> reference){

//...

}

}

publicclass Reference<Textends BaseObject>{

public Class<T> getObjectType(){

//...

}

}

But that would mean that every subclass of BaseObject<T> would need to be

declared with a type parameter as well to permit further subclassing, right?

Like so:

publicclass Fruit<Textends Fruit>extends BaseObject<T>{

// Note: T is not used in this class except to "pass it up" to BaseObject

}

publicclass Banana<Textends Banana>extends Fruit<T>{

// Note: T is not used in this class except to "pass it up" to Fruit

// Callers will have to say: new Banana<Banana>();

}

That seems WEIRD to me. Is there any way to...to...hide the genericization of

the fundamental classes--BaseObject and Reference--without forcing the type

parameters to be propagated all the way down the subclass stack?

In other words, assuming a hierarchy of Object<--Fruit<--Banana, is there any

way to have Fruit and Banana not mention type parameters at all?

Thanks,

Laird

[3263 byte] By [ljnelsona] at [2007-10-2 21:05:14]
# 1
Maybe you really want this: public class Banana extends Fruit<Banana> { }
dubwaia at 2007-7-13 23:50:31 > top of Java-index,Core,Core APIs...
# 2

> Maybe you really want this:

> >public class Banana extends Fruit<Banana> {

> }

>

But then what happens when I want to extend Banana?

L

ljnelsona at 2007-7-13 23:50:31 > top of Java-index,Core,Core APIs...
# 3

> But then what happens when I want to extend Banana?

What kind of Banana extension are you imagining?

You can always create an AbstractBanana class. Honestly, though, if you are genericizing a class and then creating tons of extended verison of it that lock down the parameter type, you may be mising the point of generics.

dubwaia at 2007-7-13 23:50:31 > top of Java-index,Core,Core APIs...
# 4

> > But then what happens when I want to extend

> Banana?

>

> What kind of Banana extension are you imagining?

>

> You can always create an AbstractBanana class.

> Honestly, though, if you are genericizing a class

> and then creating tons of extended verison of it

> that lock down the parameter type, you may be mising

> the point of generics.

Sigh; I always seem to be missing the point of generics.

I don't think an AbstractBanana class helps. I tried that. It's just another link in the inheritance stack and the same problems apply.

So what I'm getting from this is there's no way to express via generics the following edict: "Make sure if someone tries to set your reference, it's a reference of your type" (other than passing the type parameters around as in my first "solution"). Guess I'll fall back on 1.4 behavior.

Thanks,

Laird

Message was edited by:

ljnelson

ljnelsona at 2007-7-13 23:50:31 > top of Java-index,Core,Core APIs...
# 5

> Sigh; I always seem to be missing the point of

> generics.

Don't take the wrong way. I should have highlighted may in my post.

> I don't think an AbstractBanana class helps. I tried

> that. It's just another link in the inheritance

> stack and the same problems apply.

Maybe I'm missing the point of the problems. This is what I meant:

class AbstractBanana<T extends AbstractBanana> extends BaseObject<T>{//...}

class Banana extends AbstractBanana<Banana>{//...}

Most if not all the Banana logic would go in AbstractBanana.

> So what I'm getting from this is there's no way to

> express via generics the following edict: "Make sure

> if someone tries to set your reference, it's a

> reference of your type". Guess I'll fall back

> on 1.4 behavior.

I'm not sure what you mean here. There's this idiom (that's not perfect)

public class BaseObject<T extends BaseObject><T>>

dubwaia at 2007-7-13 23:50:31 > top of Java-index,Core,Core APIs...
# 6

Let me see if I can express the problem another way.

I'd like to share type information passed at the time at which a Fruit subclass is created with a Reference's type information.

That is at Banana creation time, I want it automatically to be the case that Banana's setReference() method will take only Reference<Banana>.

I'd even be moderately happy with Reference<? extends Banana>.

I'd like not to have to do silly things like this:

final Banana<Banana> b = new Banana<Banana>();

...and I'd like it NOT to be the case that overriders have to do this:

public class OrganicBanana<T extends Banana> extends Banana<T> ...

I'm up a creek here, aren't I?

L

ljnelsona at 2007-7-13 23:50:31 > top of Java-index,Core,Core APIs...
# 7

> > Sigh; I always seem to be missing the point of

> > generics.

>

> Don't take the wrong way. I should have highlighted

> may in my post.

Oh, no worries; trust me; I do miss the point of generics. :-)

Cheers,

Laird

ljnelsona at 2007-7-13 23:50:31 > top of Java-index,Core,Core APIs...
# 8

> I'm up a creek here, aren't I?

I think so. It's been a while since I complained about the lack of 'self-types' in Java. 'Self-type' actually means something different in other languages (Scala for example) so just be aware of that.

I would envision:

class BaseObject<self>

// OR

class BaseObject<T extends self>

The idea would be that self is what ever the 'current' class is. So if you used the first one, the type of the class that extended BaseObject would be assumed to be the parameteric type. The second one would require that the parameter (if present at time of variable of declaration is instantiation) be at least as specific as the current extenstion of BaseObject.

Alas, we don't have any such syntax. Scala has an interesting way of defining self-types if you are interested.

dubwaia at 2007-7-13 23:50:31 > top of Java-index,Core,Core APIs...
# 9

> > I'm up a creek here, aren't I?

>

> I think so. It's been a while since I complained

> about the lack of 'self-types' in Java. 'Self-type'

> actually means something different in other languages

> (Scala for example) so just be aware of that.

AH! Yes! That's exactly what I'm talking about. OK, knowing that I'm screwed helps a lot, actually. It lets me know where I can and cannot apply generics to solve problems.

> I would envision:

> > class BaseObject<self>

>

> // OR

>

> class BaseObject<T extends self>

>

>

> The idea would be that self is what ever the

> 'current' class is. So if you used the first one,

> the type of the class that extended BaseObject would

> be assumed to be the parameteric type. The second

> one would require that the parameter (if present at

> time of variable of declaration is instantiation) be

> at least as specific as the current extenstion of

> BaseObject.

Yes, exactly. This would be wildly helpful. Oh well.

Back to 1.4 syntax.

Cheers,

Laird

ljnelsona at 2007-7-13 23:50:31 > top of Java-index,Core,Core APIs...
# 10

> Yes, exactly. This would be wildly

> helpful. Oh well.

>

> Back to 1.4 syntax.

I'm not sure I understand this, though. 1.4 doesn't provide this ability either. I think a lot of developers would be happier with generics if they lowered their expectations. Specifically: it doesn't eliminate all casts in code and you can't express a lot of valid an useful things with the syntax.

In other words, accept generics for what they are and be happy. Oh and avoid overuse. They seem to have a corrosive effect on code when used too liberally.

dubwaia at 2007-7-13 23:50:31 > top of Java-index,Core,Core APIs...
# 11
This is called the self-type pattern for generics. Take a look at the following for more info about this problem and support (or lack thereof) for it. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6479372
jonbarrila at 2007-7-13 23:50:31 > top of Java-index,Core,Core APIs...