Generics and subclasses

E

EdwardH

I have two classes, Manager and Data. I use them as follows...

Class Manager
{
private Vector<Data1> dataVector;

add()
{
dataVector.add( new Data1(blabla) );
}
}


What I want to do is use the same Manager class use several Data-typed
classes, Data1, Data2 and Data3. They all have the same Interface but
work differently.

Unfortunately Manager doesn't want to work with Interfaces
(DataInterface, for example) because of the "new".

Does anyone have any suggestions as to how to make Manager more flexible?

Will I, as I have feared, have to make a subclass (extends) of Manager
to handle each type of Data?


PS: I've tried using generics ...

Class Manager<DataType>
private Vector<DataType> dataVector;
...
dataVector.add( new DataType(blabla) );

but once again Java doesn't know how to instanciate DataType. Interfaces
don't have constructors, it says.
 
E

EdwardH

Will I, as I have feared, have to make a subclass (extends) of Manager
to handle each type of Data?

I've solved my problem, as elegantly as it appears to be possible.

Manager handles Data.

Manager1 handles Data1.
Manager2 handles Data2.

The add() method in Manager is overloaded in each of the subManagers.
Not very elegant, forces one to keep track of all the manager subclasses
but it's better than writing the same code over and over again.
 
A

Andrew McDonagh

EdwardH said:
I've solved my problem, as elegantly as it appears to be possible.

Manager handles Data.

Manager1 handles Data1.
Manager2 handles Data2.

The add() method in Manager is overloaded in each of the subManagers.
Not very elegant, forces one to keep track of all the manager subclasses
but it's better than writing the same code over and over again.

The class names 'Manager' and 'Data' even if only used as examples - are
useless and meaningless.

What does Manager manage? What actual type are the DataXXX?

Post us your real code and we'll give you several ways of doing it
without resorting to copy and paste, Generics, voodoo....

For a starters, just because your code currently has a new statement,
doesn't mean is has too.

e.g.

Class Manager
{
private Vector<Data1> dataVector;

add()
{
// Instead of
// dataVector.add( new Data1(blabla) );

dataVector.add( DataFactory.createData(blabla);
}
}


The Factory can decide which actual DataXXX to create...

But this example is difficult to show, because Manager and Data are
rubbish names.

real code = real answers.

Andy
 
A

Andrew McDonagh

EdwardH said:
I ha
snipped...

but once again Java doesn't know how to instanciate DataType. Interfaces
don't have constructors, it says.

Thats because Interfaces are classes, and so can't be created - they are
a means of specifying what a given class looks like - nothing else.

They don't have any implementation, so there's no way for Java to know
what to do even if it let you instantiate them.

What languages do you know - we may be able to show how they are similar
to something from those languages....

Failing that, read the Java tutorial, google for Interfaces, as it
appears you have large gaps in your understanding.
 
G

Guest

I've solved my problem, as elegantly as it appears to be possible.

Manager handles Data.

Manager1 handles Data1.
Manager2 handles Data2.

The add() method in Manager is overloaded in each of the subManagers. Not
very elegant, forces one to keep track of all the manager subclasses but
it's better than writing the same code over and over again.

Why don't you just add an argument to the add-method of your Manager class?

Class Manager {
private Vector<Data> dataVector;
add(Data data){
dataVector.add(data);
}
}

Data is an interface. You create instances of Data1, Data2, Data3 (all
implementing the Data interface) outside the Manager and add them using the
add method.
If you don't want to create the instances outside the Manager you still need
a way to tell the Manager what kind of Data must be created (unless it's ok
to create them randomly), so you need some kind of argument in the
add-method and use it to determine what kind of Data must be created.
 
A

andreas kinell

EdwardH said:
I have two classes, Manager and Data. I use them as follows...

Class Manager
{
private Vector<Data1> dataVector;

add()
{
dataVector.add( new Data1(blabla) );
}
}


What I want to do is use the same Manager class use several Data-typed
classes, Data1, Data2 and Data3. They all have the same Interface but work
differently.

Unfortunately Manager doesn't want to work with Interfaces (DataInterface,
for example) because of the "new".

Does anyone have any suggestions as to how to make Manager more flexible?

I think what you want is this:

Class Manager
{
private Vector<DataInterface> dataVector;

add(){
dataVector.add( new Data1(blabla) );
}

}

class Data1 implements DataInterface{
}

notice: the dataVector accepts objects of type DataInterface. When you
actually add data, you will create a Data1 object (with "new") but it will
be of type DataInterface as well.

You seem to have overlooked that you can use Interface types like this:

DataInterface myData = new Data1();

HTH,
andreas
 
C

Chris Smith

EdwardH said:
What I want to do is use the same Manager class use several Data-typed
classes, Data1, Data2 and Data3. They all have the same Interface but
work differently.

You can use a general Manager class for this, but you'll need to play
some tricks to instantiate the Data classes.

public class Manager<T extends Data>
{
private Class<T> dataClass;
private Vector<T> dataVector;

public Manager(Class<T> c)
{
dataClass = c;
dataVector = new Vector<T>();
}

public void add()
{
try
{
T data = dataClass.newInstance();
dataVector.add(data);
}
catch (...) { ... } // error handling omitted
}
}

NOTE A: The Class<T> parameter is admittedly a bit ugly. It is required
in order to accomodate type erasure. On the other hand, at least it's
impossible to pass the wrong class as a parameter because of compile-
time checking of the generic type.

NOTE B: This assumes a zero-argument constructor. Theoretically, it's
possible to do the same thing with arguments to the constructor. In
practice, that's a bad idea because you have to clearly document a
complex constructor signature that isn't checked until runtime. If you
think you need that, then instead consider (a) adding a method to Data
-- Data.setInitialState or something like that, or (b) using an abstract
factory class instead, so you can create the factory class with no
parameters, and then pass parameters to a nice documented and type-
checked method.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

can this be done with generics? 32
Generics 12
generics puzzle 57
Generics Amanuensis? 2
constructors vs. subclasses? 4
Generics annoyance 18
How to get value among subclasses 7
Delegation and generics craziness 9

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top