From: Tom Anderson on
On Tue, 22 Jul 2008, Lew wrote:

> Tom Anderson wrote:
>
>> As i [sic] think has been explained elsewhere in the thread, what
>> you're trying to do is basically Wrong.
>
> But the SSCCE I provided for class 'Cavett' didn't seem so "Wrong". I
> disagree with your assessment that the original goal is.
>
>> If you have some specific kind of DataObject, and a collection of
>> ErrorRules for some specific kind of DataObject, then you can't just
>> apply one to the other unless the compiler can prove that the specific
>> kinds of DataObject in question are the same. That means having some
>> chain of relationships between type variables connecting the two.
>
> It makes sense that a Suite would check for only a specific kind of
> Rule, so that isn't such a terrible restriction.
>
>> The solution is probably to parameterise ErrorSuite with a type variable
>> <T extends DataObject>, and then write it to only takes ErrorRule<T> as a
>> rule and T as a subject. Or perhaps ErrorRule<? super T>, i'm not sure.
>
> All I needed to parametrize on in my SSCCE was the "T extends
> DataObject", which I renamed "Modeler" since "Object" in an object's
> name is redundant and "Data" is too wide a concept.

Whereas Modeler is merely meaningless (and misspelled)? :)

> As you say, it needs to look only at ErrorRule<T> internally. (Not "?
> super T", though, at least not the way I did it.) This seems consistent
> with the original intent.
>
> The SSCCE I provided seems to cover the OP's concerns, AFAICT. Go
> with the version where I remarked:
>
>> I eliminated the initialization override. This protects against the
>> method being called again, say by a malicious subclass.

I believe you mean this one:

http://groups.google.co.uk/group/comp.lang.java.programmer/msg/b0908cef8cfdddc0?hl=en&dmode=source

I have to confess that i only skim-read it when i first saw it.

A minor aside - as it is, i can't compile it; i get;



Cavett.java:67: method does not override a method from its superclass
@Override
^
Cavett.java:79: method does not override a method from its superclass
@Override
^
2 errors



I'm on 1.5.0_13; are you on 1.6, and is this something that's changed
between them?

Anyway, having had a look at it, i agree with you - that's exactly what i
was thinking.

My point was really about this bit:

public static void main( String[] args )
{
ErrorSuite <TestModeler> suite = new TestErrorSuite();
suite.verify( new TestModeler() {} );
}

The calling code needs to mention the type of Modeler that's being tested.
This is absolutely unavoidable if you want type safety, as this is where
the creation of the ErrorSuite and Modeler occur, and the two need to be
tied together in terms of type. I think the OP was hoping to be able to
get away without this, but to still have type safety.

Originally, i was thinking there was a hack you could do with Class.cast()
that would push some of the typechecking to runtime, and sort of let you
get away with a non-generic TestModeler, but i couldn't work out anything
useful.

tom

--
We can only see a short distance ahead, but we can see plenty there that
needs to be done. -- Alan Turing
From: Lew on
Lew wrote:
> > All I needed to parametrize on in my SSCCE was the "T extends
> > DataObject", which I renamed "Modeler" since "Object" in an object's
> > name is redundant and "Data" is too wide a concept.
>
> Whereas Modeler is merely meaningless (and misspelled)? :)

Neither:
<http://en.wiktionary.org/wiki/modeler>

> > As you say, it needs to look only at ErrorRule<T> internally.  (Not "?
> > super T", though, at least not the way I did it.)  This seems consistent
> > with the original intent.
>
> > The SSCCE I provided seems to cover the OP's concerns, AFAICT.  Go
> > with the version where I remarked:
>
> >> I eliminated the initialization override. This protects against the
> >> method being called again, say by a malicious subclass.
>
> I believe you mean this one:
>
> http://groups.google.co.uk/group/comp.lang.java.programmer/msg/b0908c...

Yes.

> I have to confess that i only skim-read it when i first saw it.

Oh, well. It was totally fun for me - a true generics puzzler. I
learned a lot from writing it.

> A minor aside - as it is, i can't compile it; i get;
>
> Cavett.java:67: method does not override a method from its superclass
>           @Override
>            ^
> Cavett.java:79: method does not override a method from its superclass
>           @Override
>            ^
> 2 errors

I think it's the annotation.

> I'm on 1.5.0_13; are you on 1.6, and is this something that's changed
> between them?

I wouldn't have thought so, but I think they changed @Override to
apply to interfaces as well as classes. Try refactoring the
interfaces as abstract classes; if that makes the error go away then
you're on to something.

Java 5 is in End-of-Life phase, so you might want to move to the
current version anyway.

> Anyway, having had a look at it, i agree with you - that's exactly what i
> was thinking.
>
> My point was really about this bit:
>
>       public static void main( String[] args )
>       {
>           ErrorSuite <TestModeler> suite = new TestErrorSuite();
>           suite.verify( new TestModeler() {} );
>       }
>
> The calling code needs to mention the type of Modeler that's being tested..
> This is absolutely unavoidable if you want type safety, as this is where
> the creation of the ErrorSuite and Modeler occur, and the two need to be
> tied together in terms of type. I think the OP was hoping to be able to
> get away without this, but to still have type safety.

I agree, one must tie things together somehow, but I just don't see
this as a very narrow restriction. If an ErrorSuite intends to deal
with any old Modeler then the Rule has to be able to accept any old
Modeler; you cannot restrict the Rule more than the ErrorSuite. The
type-safety concerns mirror the logical decomposition of the problem.

> Originally, i was thinking there was a hack you could do with Class.cast()
> that would push some of the typechecking to runtime, and sort of let you
> get away with a non-generic TestModeler, but i couldn't work out anything
> useful.

I like the compile-time safety more than run-time.

--
Lew
From: thufir on
On Thu, 17 Jul 2008 09:12:04 -0700, maaxiim wrote:


> public class TestErrorSuite {
> public class DataObject {
> }
>
> public class TestObject extends DataObject { }
>
> public abstract class ErrorRule<T extends DataObject> {
> public abstract boolean verify(T object);
> }
>
> public class ErrorSuite<T extends DataObject> {
> Set<ErrorRule<T>> rules = new HashSet<ErrorRule<T>>();


This is saying that the set takes ErrorRule<T> as a parameter, or, if I'm
not mistaken, anything which which inherits it? Would it be better if
ErrorRule<T> were an interface?



-Thufir