Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > abstract classes and generic types

Reply
Thread Tools

abstract classes and generic types

 
 
Mark Space
Guest
Posts: n/a
 
      05-17-2009
I think I came up with the same thing Giovanni did, except "put" needs
to return a String to match your example.

http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

abstract class a<U>
> {
> String calculate() { return this.put(this.my_func()); }

abstract String put( U u );
abstract U my_func();
> }
>


Otherwise use this the same way as his example.

Note: you can' parameterize with primitives. If you want to use float
or int, gotta write those by hand yourself. Sorry.


 
Reply With Quote
 
 
 
 
Lew
Guest
Posts: n/a
 
      05-17-2009
Mark Space wrote:
> Note: you can' parameterize with primitives. If you want to use float
> or int, gotta write those by hand yourself. Sorry.


Or use Float and Integer.

--
Lew
 
Reply With Quote
 
 
 
 
horos11@gmail.com
Guest
Posts: n/a
 
      05-17-2009
On May 17, 3:29*pm, Mark Space <(E-Mail Removed)> wrote:
> I think I came up with the same thing Giovanni did, except "put" needs
> to return a String to match your example.
>
> (E-Mail Removed) wrote:
>
> abstract class a<U>> {
> > * * String calculate() { return this.put(this.my_func()); }

>
> * * * *abstract String put( U u );
> * * * *abstract U my_func();
>
> > }

>
> Otherwise use this the same way as his example.
>
> Note: *you can' parameterize with primitives. *If you want to use float
> or int, gotta write those by hand yourself. *Sorry.


Ok, I guess I'll morph this issue a bit. I came to the conclusion that
generics were the way to go, but why should I need to define a
parameter with a class to do what I want to do?

I think of the types of variables in an object as implementation
details.. But the following doesn't work:

import java.util.*;
class AA
{

Set<?> example;

aa()
{
example = new HashSet<Integer>();
_setHelper(example, new Integer(1));
System.out.println(example);
}

private<K> void _setHelper(Set<K> parm, K key)
{
parm.add(key);
}
}

where I'm attempting to give the compiler a little push in the right
direction, showing that Set<K> should be linked with the ?. I would
have thought this would have worked, but no.

Of course, if I explicitly cast it - (Set<Integer>)example, it works,
but that gets rid of the point of generics, doesn't it?

So any ideas around this?

(ps - wrt language lawyering, with all respect I detest camelcase, and
will only use it if required by convention. And no - I don't go around
naming my variables mySet, etc.. I do it for example.. so thanks for
the concern, but no thanks..
 
Reply With Quote
 
horos11@gmail.com
Guest
Posts: n/a
 
      05-18-2009
BTW - with the below I did find a workaround. If I say:

private<K> void _setHelper(Set<K> parm, Integer key)
{
parm.add((K) key);
}

ie, ie explicitly cast it, this works. But it also tells me that I'm
using unsafe operations.
This should not be unsafe - there's got to be a better solution than
this out there. Else are generics inherently unsafe?


> import java.util.*;
> class AA
> {
>
> * * Set<?> example;
>
> * * aa()
> * * {
> * * * * *example = new HashSet<Integer>();
> * * * * _setHelper(example, new Integer(1));
> * * * * *System.out.println(example);
> * * }
>
> * * private<K> void _setHelper(Set<K> parm, K key)
> * * {
> * * * * parm.add(key);
> * * }
>
> }
>
> where I'm attempting to give the compiler a little push in the right
> direction, showing that Set<K> should be linked with the ?. I would
> have thought this would have worked, but no.
>
> Of course, if I explicitly cast it - (Set<Integer>)example, it works,
> but that gets rid of the point of generics, doesn't it?
>
> So any ideas around this?
>
> (ps - wrt language lawyering, with all respect I detest camelcase, and
> will only use it if required by convention. And no - I don't go around
> naming my variables mySet, etc.. I do it for example.. so thanks for
> the concern, but no thanks..


 
Reply With Quote
 
Lew
Guest
Posts: n/a
 
      05-18-2009
(E-Mail Removed) wrote:
> Ok, I guess I'll morph this issue a bit. I came to the conclusion that
> generics were the way to go, but why should I need to define a
> parameter with a class to do what I want to do?


Because that's how Java does it.

> I think of the types of variables in an object as implementation
> details.. But the following doesn't work:
>
> import java.util.*;
> class AA
> {
>
> Set<?> example;
>
> aa()


The constructor name must match the class name. This line as shown will not
compile, as it is legal for neither constructor nor method.

Both class and constructor must be public if you wish to use them outside the
package in which they're defined.

> {
> example = new HashSet<Integer>();
> _setHelper(example, new Integer(1));
> System.out.println(example);
> }
>
> private<K> void _setHelper(Set<K> parm, K key)


Convention has it that one not use underscores in method names.

To your actual point, 'Set<?>' and 'Set<K>' have different meanings. Just
telling the method that the 'Set<?>' is actually a 'Set<Integer>' isn't quite
enough. Generally, with "extends" wildcards (? is shorthand for "? extends
Object"), you cannot safely "put()" (i.e., "add()" in this context).

See these articles:
<http://java.sun.com/docs/books/tutorial/extra/generics/index.html>
particularly,
<http://java.sun.com/docs/books/tutorial/extra/generics/wildcards.html>

<http://www.ibm.com/developerworks/java/library/j-jtp04298.html>
<http://www.ibm.com/developerworks/java/library/j-jtp07018.html>

The compiler errors will indicate what you did wrong, but in more general
terms, you aren't locking down your type analysis with this kind of thing. If
'example' is meant to be a 'Set<Integer>', it should be declared as such. If
the whole class is meant to be a general handler for different types of sets,
where the instance will deal throughout with the same type, then the class
itself should have the type parameter. Also, there's little point in passing
a member variable as an argument to a member method of the same class. It
already has access to the member variable.

> {
> parm.add(key);
> }
> }
>
> where I'm attempting to give the compiler a little push in the right
> direction, showing that Set<K> should be linked with the ?. I would
> have thought this would have worked, but no.


That's because you are misusing the generics syntax. The right way to do this
is to have the <K> in the 'Set' declaration itself. You were trying to tell
the compiler that 'Set' can have literally any type of object in it with the
<?>, and also simultaneously that it can only have 'K' (in this case,
'Integer') in it. You can't get both promises at the same time because they
contradict each other.

Furthermore, <?> means that whatever type 'Set' contains, all its elements are
of that type. If your method were legal, it could be called at different
times with different 'K' types, all trying to 'add()' to the same set. That
wouldn't be legal either.

> Of course, if I explicitly cast it - (Set<Integer>)example, it works,
> but that gets rid of the point of generics, doesn't it?


It does generate a warning to that effect.

It was the failure to lock down the 'example' type parameter to that of the
method that got rid of that point, actually.

> So any ideas around this?


Do it like this:

public class AA
{

Set<Integer> example = new HashSet<Integer>();

public void loadAndPrintln()
{
example.add( Integer.valueOf(1) );
System.out.println( example );
}
}

If you want 'AA' to be generic so that client code can use it for 'Integer',
'String' or whatever, the generic parameter should be on the class itself.

public class AA <K>
{
Set <K> example = new HashSet <K> ();

public void loadAndPrintln( K value )
{
example.add( value );
System.out.println( example );
}
}

That's kind of the point of generics, isn't it?

> (ps [sic] - wrt language lawyering, with all respect I detest camelcase, and
> will only use it if required by convention. And no - I don't go around


It is "required" by convention. It is not a question of "language lawyering",
as you so disparagingly put it, but of communication. The language itself
lets you do things differently, but that doesn't mean that you should do
things differently. The conventions make life easier in a world where one is
not the only resident.

However, whatever convention you do follow, the constructor name must match
the case of the class name. The compiler will refuse to cooperate if you don't.

> naming my variables mySet, etc.. I do it for example.. so thanks for
> the concern, but no thanks..


One period suffices to indicate a declarative sentence.

--
Lew
 
Reply With Quote
 
Lew
Guest
Posts: n/a
 
      05-18-2009
(E-Mail Removed) wrote:
> BTW - with the below I did find a workaround. If I say:
>
> private<K> void _setHelper(Set<K> parm, Integer key)
> {
> parm.add((K) key);
> }
>
> ie, ie explicitly cast it, this works. But it also tells me that I'm
> using unsafe operations.
> This should not be unsafe - there's got to be a better solution than
> this out there. Else are generics inherently unsafe?


No, generics make life more safe. What you did intentionally broke the
promises that generics tries to keep, so that was what was unsafe.

If you read the rules for generics, you will see that they are compile-time
constructs, and that casts to a parametric type, being a run-time phenomenon,
are therefore not really what generics handle. Thus the warning.

Correct use of generics, which follows hard on correct if difficult detailed
type analysis, will eliminate both the need for the cast and the warning.

--
Lew
 
Reply With Quote
 
Mark Space
Guest
Posts: n/a
 
      05-18-2009
(E-Mail Removed) wrote:
> BTW - with the below I did find a workaround. If I say:
>
> private<K> void _setHelper(Set<K> parm, Integer key)
> {
> parm.add((K) key);
> }
>
> ie, ie explicitly cast it, this works. But it also tells me that I'm
> using unsafe operations.
> This should not be unsafe - there's got to be a better solution than
> this out there. Else are generics inherently unsafe?


No, they're safe, just the way you are using them isn't.

First, I want to point out that if you follow Giovanni's advice, the end
user never sees the generic declaration.

class AA<T> {}

class BB extends AA<Integer> {}

The user just uses BB as a normal class:

BB bb = new BB();

So I don't see why you want to get rid of generics. However, if you do,
then I think something like this will work:

class AA {}

class BB {} extends AA {
Set<Integer> example;
BB() {
example = newHashSet<Integer>();
example.add( new Integer() );
System.out.println( example );
}
}

No need for the helper method, but in this case you do need to declare
the Set<> yourself (which you were basically doing anyway when you
called "new").
 
Reply With Quote
 
Tom Anderson
Guest
Posts: n/a
 
      05-18-2009
On Sun, 17 May 2009, (E-Mail Removed) wrote:

> On May 17, 3:29*pm, Mark Space <(E-Mail Removed)> wrote:
>> I think I came up with the same thing Giovanni did, except "put" needs
>> to return a String to match your example.
>>
>> (E-Mail Removed) wrote:
>>
>> abstract class a<U>> {
>>> * * String calculate() { return this.put(this.my_func()); }

>>
>> * * * *abstract String put( U u );
>> * * * *abstract U my_func();
>>
>>> }

>>
>> Otherwise use this the same way as his example.
>>
>> Note: *you can' parameterize with primitives. *If you want to use float
>> or int, gotta write those by hand yourself. *Sorry.

>
> Ok, I guess I'll morph this issue a bit. I came to the conclusion that
> generics were the way to go, but why should I need to define a parameter
> with a class to do what I want to do?


This has been discussed here many times before. The upshot is that because
of the way java's generics work, you can't get away from defining the
parameter as part of the exposed interface. You require clients to write:

HorosFunkyClass<?>

Instead of just:

HorosFunkyClass

When dealing with it polymorphically. This is a wart, but a small one.

However ...

I have thought of a way you could do it without the wart, using
deviousness.

The trick is to push the variable into another, private, class, and then
refer to it via a <?>-bound variable. You can then manipulate that object
via a private generic method, which provides a local type-bound context to
do the work in. I should warn you that this is third-level generics
voodoo.

Here we go:

abstract class FunkyClass {
private FunkyHelper<?> helper;

protected FunkyClass(FunkyHelper<?> helper) {
this.helper = helper;
}
public void calculate() {
doCalculate(helper);
}
private <T> void doCalculate(FunkyHelper<T> helper) {
helper.things.add(helper.myFunc());
}
}

class IntegerFunky extends FunkyClass {
public IntegerFunky() {
super(new IntegerFunkyHelper());
}
}

class FloatFunky extends FunkyClass {
public FloatFunky() {
super(new FloatFunkyHelper());
}
}

abstract class FunkyHelper<T> {
public Set<T> things;
public abstract T myFunc();
}

class IntegerFunkyHelper extends FunkyHelper<Integer> {
public Integer myFunc() {
return 1;
}
}

class FloatFunkyHelper extends FunkyHelper<Float> {
public Float myFunc() {
return 1.0f;
}
}

Study and be enlightened.

tom

--
I am become Life, destroyer of worlds
 
Reply With Quote
 
Roedy Green
Guest
Posts: n/a
 
      05-18-2009
On Sun, 17 May 2009 11:33:02 -0700 (PDT), (E-Mail Removed) wrote,
quoted or indirectly quoted someone who said :

>
>Is there a way to do this, or am I pretty much stuck reimplementing
>lots of functionality in each subclass?


this sort of problem is sometimes solved with a set of has-a functions
rather than is-a.

You provide the functionality via a delegate object referred to by the
class. Think of it as hiring specialised servants rather that doing
all the work yourself.

see http://mindprod.com/jgloss/callback.html
http://mindprod.com/jgloss/delegate.html
http://mindprod.com/jgloss/isa.html
--
Roedy Green Canadian Mind Products
http://mindprod.com

"It wasnít the Exxon Valdez captainís driving that caused the Alaskan oil spill. It was yours."
~ Greenpeace advertisement New York Times 1990-02-25
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
"Incompatible types" error though types are same generic type wdh3rd@gmail.com Java 3 04-15-2007 02:36 PM
what is the difference between abstract class and pure abstract class? skishorev@yahoo.co.in C++ 4 05-17-2006 08:07 AM
Vector of abstract classes filled with derived classes ? Manuel C++ 8 01-05-2006 09:07 PM
About abstract class and abstract method Sameer Java 4 08-31-2005 12:59 AM
Abstract Classes w/o abstract methods DaKoadMunky Java 4 04-20-2004 04:53 AM



Advertisments