Reputation: 1427
I have some custom classes, which contain information about different viewtypes in a RecyclerView
, like title, description, etc (there are different variables for each class though). I want to add these classes to an ArrayList
, but I don't want it to be a generic (Object?) ArrayList
, I want to make sure only my custom classes can be put in. Now I could do this by making another class for it with a setter and getter, and do some checks, but I'd rather have something like ArrayList<CustomGroup>
, where CustomGroup
could be any of CustomClass1
, CustomClass2
, etc... Is this possible, and if so, how would I do this?
Example:
public class CustomClass1 {
String title, description;
int amount;
// Getter & Setter
}
public class CustomClass2 {
String errorMessage;
int errorCode;
// Getter & Setter
}
public class CustomClass3 {
String warningName;
double amount;
// Getter & Setter
}
ArrayList<CustomGroup> arrayList = new ArrayList<>();
CustomClass3 customClass3 = new CustomClass3();
// Set values for customClass3
arrayList.add(customClass3);
CustomClass1 customClass1 = new CustomClass1();
// Set values for customClass1
arrayList.add(customClass1);
Upvotes: 1
Views: 114
Reputation: 13930
I would agree with the other answer which suggests using an interface. I would add that, since the examples that you show do not have the same types, you'll find yourself doing checks; perhaps like:
if (someClass instanceof CustomClass1) {
...
} else if (someClass instanceof CustomClass2) {
...
} else if (someClass instanceof CustomClassN) {
...
} else { ... }
That's not very extensible or easily maintained.
You could use the interface, whether empty or with common attributes of the same type, but it might get ugly though doing said checks. Maybe what you could do to avoid that is add a CustomClassProcessor
class which will have overloaded methods for the various types you have to handle; this is called the visitor pattern.
public class CustomClassProcessor {
public void process(CustomClass1 cc) {
// Do stuff for CustomClass1
}
public void process(CustomClass2 cc) {
// Do stuff for CustomClass2
}
public void process(CustomClass cc) {
// Do stuff for CustomClass3
}
...
}
Your interface would be like so:
public interface CustomClass {
public void getProcessed(CustomClassProcessor cp);
}
One example of a concrete custom class would be:
public class CustomClass1 implements CustomClass {
@Override
public void getProcessed(CustomClassProcessor cp) {
cp.process(this);
}
}
And you'd use it like:
for (CustomClass cc : list)
cc.getProcessed(customClassProcessor);
or with Java 8 features...
list.forEach(cc -> cc.getProcessed(customClassProcessor);
Upvotes: 0
Reputation: 9925
You have several absolutely different objects and requirement to join it with array list to show it in recyclerView by position. So you have to use ArrayList of Object's(or another collection of objects) and you can't avoid it and pospone checking types.
You have to create such list and make connection of concrete class of stored object with item type (in getItemType) via using instanceof. After that you can create viewHolders according to these types and then in onBindViewHolder cast current item to connected viewHolder or encapsulate casting in concrete view holders
Upvotes: -2
Reputation: 589
I would recommend using an interface for this. You can use interfaces as "tags", where the interface basically defines nothing but the classes you want to allow in the list implement it. In your case, however, you could have the interface define the String and int properties.
Interface "tag" with nothing specified
public interface ICustomClassInterface {
}
public class CustomClass1 implements ICustomClassInterface {
String title, description;
int amount;
}
ArrayList<ICustomClassInterface> arrayList = new ArrayList<ICustomClassInterface>();
Only classes that implement the interface can be added to the list. However, your issue here is you will be getting to them through this interface which defines nothing, i.e. you will need to figure out what type it is.
Ideally you would refactor your classes to have the common functionality either defined in an abstract class or specified in an interface, then you don't need to care what the actual type is.
Interface with needed properties defined
public interface ICustomClassInterface {
String FieldA;
int FieldB;
}
public CustomClass1 implements ICustomClassInterface {
String FieldA;
int FieldB;
}
ArrayList<ICustomClassInterface> arrayList = new ArrayList<ICustomClassInterface>();
Upvotes: 4