Extending ArrayList and Creating new methods - java

I'm having a bit of a problem grasping something - I might be going about this completely wrong.
I am trying to create a class which extends ArrayList but has several methods which increase the functionality (at least for the program I am developing.)
One of the methods is a findById(int id), which searches each ArrayList object for a particular id match. So far it's working, but it won't let me do for (Item i : this) { i.getId(); }
I don't understand why?
Full code:
public class CustomArrayList<Item> extends ArrayList<Item> {
// declare singleton instance
protected static CustomArrayList instance;
// private constructor
private CustomArrayList(){
// do nothing
}
// get instance of class - singleton
public static CustomArrayList getInstance(){
if (instance == null){
instance = new CustomArrayList();
}
return instance;
}
public Item findById(int id){
Item item = null;
for (Item i : this) {
if (i.getId() == id) {
// something
}
}
return item;
}
public void printList(){
String print = "";
for (Item i : this) {
print += i.toString() + "\n";
}
System.out.println(print);
}
}

Change
public class CustomArrayList<Item> extends ArrayList<Item> {
to
public class CustomArrayList extends ArrayList<Item> {
I suspect Item is the name of the class that you want to store in the list. By adding <Item> after CustomArrayList you're introducing a type parameter which shadows this class.
With the <Item> parameter, your code is equal to
public class CustomArrayList<T> extends ArrayList<T> {
// ...
for (T i : this) { i.getId(); }
// ...
}
which obviously won't always work, as T may refer to any type.

What is getId()? Presumably it's a method in some class, but we don't know which class.
If you've actually got a class called Item with a getId() method, which this is meant to be a list of, you simply need to stop your class from being generic. So instead of this:
public class CustomArrayList<Item> extends ArrayList<Item> {
you want:
public class CustomArrayList extends ArrayList<Item> {
Currently within your class, Item doesn't refer to a class called Item, it refers to a type parameter called Item.
Now personally:
I wouldn't avoid creating singletons unless you really have to
If you have to, I'd avoid creating them in the way you have (which isn't thread-safe)
I wouldn't extend ArrayList<> unless I really had to, preferring composition over inheritance

Related

How to call a getter from a subclass which hasn't an abstract declaration in the superclass

I have a superclass that I instantiate as ArrayList. A subclass of the superclass is saved in the ArrayList. Now I want to get the information out of the ArrayList, but the getter for the attribute is only available in the subclass. I can get the information (which are saved in the ArrayList too) from other classes that have an abstract declaration in the abstract superclass. However, I don’t like to implement “dummy” methods in all classes which extend the superclass.
Code truncated:
public class Question{
QuestionPool() {
questionPool = new ArrayList<Question>();
ClozeQuestions q15 = new ClozeQuestions("Erster Text", "Zweiter Text");
questionPool.add(q15);
}
public int startQuiz{
System.out.printf("Q: %s", questionPool.get(i).?????
}
}
public abstract class Question {
String question;
public String getQuestion() {
return question;
}
}
public class ClozeQuestions extends Question {
ClozeQuestions(String questionPart1, String questionPart2){
this.questionPart1 = questionPart1;
this.questionPart2 = questionPart2;
}
public String getQuestionPart1() {
return questionPart1;
}
public String getQuestionPart2() {
return questionPart2;
}
}
To circumvent the problem I implemented a "helper method" in the Question class:
ClozeQuestions question2ClozeQuestion = new ClozeQuestions();
return question2ClozeQuestion.getQuestionPart1();
}
Which I call from the QuestionPool class:
System.out.printf("Q: %s", questionPool.get(i).getQuestionPart1());
Since the objects in the list are stored as the type of the superclass, you will have to cast it to the subclass before you can access the subclass methods. This is what type casting looks like:
(Subclass)objectOfSuperclassType
And to be safe, you should type check before casting which can be done with 'instanceof':
if (objectOfSuperclassType instanceof Subclass) {
Subclass objectOfSubclassType = (Subclass)objectOfSuperClass
}
And finally, an example of how to implement this when dealing with a list:
List<Superclass> myList = new ArrayList<>();
myList.add(new Subclass());
if (myList.get(0) instanceof Subclass) {
System.out.println( ((Subclass) myList.get(0)).getSomeString() );
}
Although this may answer your question, the code you provided does not require the List to be initialized with the superclass at all. If you were to have two different subclasses and stored both of them in the same list, only then would it make sense to do this.

Avoid using multiple if-else statements

Item is an abstract class with subclasses Potion, Weapon. Shield.
The useItem() method is an abstract method defined in each of Item's subclasses
get_item return object of class Item
The getItem method returns an object of class subclass of Item
case "use":
if (hero.get_item() instanceof Potion) {
hero.<Potion>getItem(Potion.class).useItem();
} else if (hero.get_item() instanceof Weapon) {
hero.<Weapon>getItem(Weapon.class).useItem();
} else if (hero.get_item() instanceof Shield) {
hero.<Shield>getItem(Shield.class).useItem();
}
break;
is there a way I can condense this code into something like...
Class itemclass = hero.getItem().getClass();
hero.<itemclass>getItem(itemclass.class).useItem();
The code above does not compile but I am looking for something like it. I am trying to avoid if else statements because there are many more items.
Edit:
The reason i did not initially use hero.get_item().useItem() was because
i was trying to do
Weapon sword = hero.get_item();
so i could access methods such as sword.getDamage()
However, I would get the error error: incompatible types: Item cannot be converted to a Weapon
so that is why I created (help from #marsouf) hero.<Weapon>getItem(Weapon.class)
Today i created the method abstract public void useItem();
and since it is a method of the Item class I am able to use hero.getItem().useItem()
It would make more sense to haven an Interface for Item with the method useItem().
Then have an implementation for Potion, Shield etc.
This way you avoid having to cast and make it more complex than it is.
useItem() does not belong in the abstract class if its not giving any functionality, and less needed now Interfaces can have default methods.
My idea is to use the magic of generics without not cast
public class Character<T extends Item> {
private T item;
public Character (T item){
this.item = item;
}
public T getItem(){
return item;
}
}
When you create a hero:
Character hero = new Character<Weapon>(new Weapon("sword"));
after this you can use it like:
hero.getItem().useItem(); // abstract method from Item class
hero.getItem().getPower(); //where power is a Weapon method
Character class you can extend like:
public class Hero<T> extend Character<T>{
//add there your custom methods or override Character methods
}
Difficult to answer without seeing the contracts being involved (hero.get_item(), hero.getItem()).
But have you tried:
Class<?> itemClass = hero.get_item().getClass();
hero.getItem(itemClass).useIt();
?
Assuming you are set on using generics the way you're using them... here's how.
First, I've created some extremely simple classes to mimic your structure from this and your other question: a class which uses instances of a particular abstract class.
public class ACOne extends AbstractClass
{
#Override
public void use(){System.out.println("Used item ACOne!");}
}
public class ACTwo extends AbstractClass
{
#Override
public void use(){System.out.println("Used item ACTwo!");}
}
public abstract class AbstractClass
{
public abstract void use();
}
public class UserClass
{
private AbstractClass item;
public UserClass (AbstractClass item)
{
this.item = item;
}
public Class<? extends AbstractClass> getItemClass()
{
return item.getClass();
}
public <T extends AbstractClass> T getItem (Class <? extends T> targetType)
{
return targetType.cast(this.item);
}
public void setItem (AbstractClass item)
{
this.item = item;
}
}
public class CastingSubclasses
{
public void testCastingSubclasses()
{
UserClass user = new UserClass(new ACOne());
user.setItem(new ACTwo());
user.getItem(user.getItemClass()).use();
}
}
This program, when run, prints out "Used item ACTwo!"
The crux here is in the getItemClass method on the UserClass (your Character class).
Also, it's common to call these methods which get the Class object 'getClazz', since there is a default method 'getClass' that you don't want to override.
Here it made sense to just keep the spelling.

How to avoid null checking - OOP

I am making a game and I have a Tile class that contains an Item.
public clas Tile{
Item item;
....
public void setItem(Item item){
this.item = item;
}
}
When I have a reference to the Tile I want to call the interact() method on the item. How can I do this without checking if the object is null. I don't think the Null Object pattern will work in this scenario because there will be mixed instance cohesion - a subclass of item that would represent an empty item would have an empty interact() method.
You are trying to find a way to not check if the object is null, when null is an option.
In this case, design to check if item != null, before execute item.interact(), is not an anti-pattern or hacking solution.
The stereotypical solution to the mixed instance cohesion problem is to create subclasses (and make sure that the superclass doesn't expose the subclass-specific functionality).
So you create a ItemTile and NonItemTile subclass of Tile.
public abstract class Tile {
public abstract void interact();
}
public class ItemTile extends Tile {
private final Item item;
....
public ItemTile(Item item) {
// Null-check to enforce contract - could be omitted if you make this
// the responsibility of the caller.
if (item == null)
throw new NullPointerException("item");
this.item = item;
}
public void interact() {
item.interact();
}
}

How to determine current class type?

I had 2 classes, B and C, who needed to keep track of their instances, so each of them has an ArrayList of their respective types to which instances were added in the constructor.
Since this seemed like common behaviour, I tried to find some sort of standard Java interface or class that expresses this behaviour, something like an InstanceManager interface. I didn't find any
I ended up trying to write an abstract class for it and I got stuck because I don't know how to specify the specific type of the subclasses.
For example:
public abstract class C { public static ArrayList<C> list; }
public class A extends C { }
public class B extends C { }
In this case, B.list or A.list would be lists of C objects, but I would actually want them to be lists of B and A objects, respectively.
Is there any way I could make that happen easily?
I am thinking something along the lines of
public abstract class C { public static ArrayList<thisclass> list; }
but that would obviously not work.
I realise that I could probably use generics to handle this, but it feels redundant and I can't help wishing that there is a way to somehow infer the child class type in this situation.
Also, is there any standard Java interface for handling instance management or unique instance id generation?
EDIT:
I have come to understand that static variables are not inherited, and the subclasses' static variables actually refer to the same thing. As such, is there any way I can define instance managing behaviour without resorting to redundancy, having to write the same things in all subclasses?
It's already been pointed out that a Map is appropriate here; however there are a few other concerns:
Multithreading.
Garbage collection.
#1 is fairly easy to factor in but worthwhile to point out.
#2 is important because you want to think carefully about whether or not keeping a list of all instances should prevent them from being garbage collected. If not, you need to become familiar with the WeakReference class.
Here is an example of the more complicated case.
public final class InstanceManager<T> {
private final Map<Class<?>, List<Reference<T>>> refMap = (
new HashMap<Class<?>, List<Reference<T>>>()
);
public synchronized <U extends T> U manage(U instance) {
Class<?> cls = instance.getClass();
List<Reference<T>> refList = refMap.get(cls);
if(refList == null) {
refList = new LinkedList<Reference<T>>();
refMap.put(cls, refList);
}
refList.add(new WeakReference<T>(instance));
return instance;
}
public synchronized <U extends T> List<U> getAll(Class<U> cls) {
List<U> returnList = new LinkedList<U>();
List<Reference<T>> refList = refMap.get(cls);
if(refList != null) {
Iterator<Reference<T>> it = refList.iterator();
while(it.hasNext()) {
T instance = it.next().get();
if(instance == null) {
it.remove();
} else {
returnList.add(cls.cast(instance));
}
}
}
return returnList;
}
}
As an example of usage,
InstanceManager<Object> im = new InstanceManager<Object>();
Object o1 = im.manage(new Object());
Object o2 = im.manage(new Object());
String s1 = im.manage("a");
String s2 = im.manage(new String("b"));
System.out.println("Object count: " + im.getAll(Object.class).size());
System.out.println("String count: " + im.getAll(String.class).size());
o2 = s1 = s2 = null;
System.gc();
Thread.sleep(1000);
System.out.println("Object count: " + im.getAll(Object.class).size());
System.out.println("String count: " + im.getAll(String.class).size());
The output here is
Object count: 2
String count: 2
Object count: 1
String count: 1
because this InstanceManager allows its referents to be garbage collected. If that's not the desired behavior (you aren't keeping references to the instances elsewhere) then of course you need to release them manually.
But either way this allows you to do something like
public abstract class C {
private static final InstanceManager<C> manager = new InstanceManager<C>();
protected C() {
manager.manage(this);
}
}
where all instances of C and its subclasses are automatically managed and categorized by actual type.
Using generics, you can do something like:
abstract class C<T> {
public List<T> list;
}
class A extends C<A> {
}
class B extends C<B> {
}
Keep a class name to list of instances mapping, determine the type at runtime to insert instances to the appropriate list:
Map<String,List<?>> instances;
....
instances.get(instance.getClass().getName()).add(instance);

Use instanceof or public method to get instance

So I have 3 classes:
Item
GroupItem extends Item
ProductItem extends Item
I am passing a array of Item objects to a class and want to do separate things depending on their class type.
Would using instanceof be an acceptable way of doing this or should I have an internal boolean isGroup() method which will be set on initialisation of the specified sub-class.
class Item {
protected boolean isGroup = false;
public boolean isGroupItem() { return isGroup; }
}
class GroupItem extends Item {
public GroupItem() {
isGroup = true;
}
}
class ProductItem extends Item {
public ProductItem() {
isGroup = false;
}
}
class Promotion {
// Item can be either a group or a list of items
private List<Item> items = new LinkedList<Item>;
public void addItem(Item itemObj) {
items.addItem(itemObj);
}
public List<Item> getItems() {
return items;
}
}
class Checker {
// Items retrieved from Promotion and passed from another class as array
public Checker(Item[] items) {
// either
if(items[0] instanceof GroupItem) {
// Do something ...
}
// or
if(items[0].isGroupItem()) {
// Do something ...
}
}
}
So my questions are:
instanceof or method?
if method, in Item or Promotion?
and, Why? (Just so i can better understand the reasoning)
Thanks in advance
Use different methods on the actual type you want to pass as parameter.
Usually, using instance of means that there is something wrong in your model.
If you need to have different behaviors for different subtypes, it means that you are not really using the parent type. In addition, you are compelled to know the implementation details, which should not be the case.
If the inheritance you have is only a technical one, try to use composition instead of inheritance.
This is the exact place where you should use instanceOf operator .
The instanceof operator compares an object to a specified type. You
can use it to test if an object is an instance of a class, an instance
of a subclass, or an instance of a class that implements a particular
interface.
There is no point to skatch a new method or some boolean property to do this stuff. You can easily identify specific Object of GroupItem by check instanceOf.
you can also use GroupItem.class.isInstance(items[0]) to check the same. like -
if(GroupItem.class.isInstance(items[0])) {
// Do something ...
}
I guess I would try to define why I need to know if it is a group at this point.
Let's say it is to decide if one Item is eligible for a promotion and the promotion rules might change: then I would use instanceof, because you don't want the promotion rules logic to "pollute" your basic objects.
If being a group is an important property of your item and is useful in various contexts (not just the promotion rules), I would include it at the Item level.
The instaceOf operator is a better choice but I would also consider to use the Visitor pattern.
interface Item{
void accept(CheckerVisitor checker);
}
class GroupItem implements Item{
void accept(CheckerVisitor checker){
checker.visit(this);
}
}
class OtherItem implements Item{
void accept(CheckerVisitor checker){
checker.visit(this);
}
}
class CheckerVisitor{
void visit(GroupItem groupItem){
//do specific things to GroupItem
}
void visit(OtherItem otherItem){}
}
class MyClassOfItems{
List<Item> items = ...;
for(Item item : items){
item.accept(new CheckerVisitor());
}
}
So after reading this i chose a different path for my solution. Thanks for everyone who helped.
The solution I chose allows me to not even be bothered with what sub-type the object is (thanks to Assylias and Balázs Mária Németh for making me rethink my structure) as I use abstract classes to just get the information i need.
abstract class Item {
public Item(...) {
initialise();
createSQLSegment();
}
protected String SQLSegment = "";
protected abstract void createSQLSegment();
public String getSQLSegment() {
return SQLSegment;
}
...
}
// Concrete class creates response
class GroupItem extends Item {
...
// Concrete method
protected void createSQLStatement() {
SQLStatement = "...SQL...";
}
}
class ProductItem extends Item {
...
// Concrete method
protected void createSQLSegment() {
SQLSegment = "...SQL..."
}
}
class Promotion {
// Item can be either a group or a list of items? extends Item>;
public void addItem(Item itemObj) {
items.addItem(itemObj);
}
public List<Item> getItems() {
return items;
}
}
class Checker {
// Items retrieved from Promotion and passed from another class as array
public Checker(Item[] items) {
...
for(Item item : Items) {
addPreparedSQLToBatch(item);
}
}
private void addPreparedItemToBatch(Item item) {
...
// No need to know concrete class
SQLString += Item.getSQLSegment();
...
}
}
Thanks again to everyone.
Comments welcome, I'm always learning :-)

Categories