How to avoid null checking - OOP - java

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();
}
}

Related

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.

Meaning of "this" in this code?

public boolean contains(Object o) {
for (E x : this)
if (x.equals(o))
return true;
return false;
}
Can someone tell me what excatly means "this" in this code? Can I write it without this and how?
Here this represents object on which current method was invoked. For instance if you have a.contains(x) then inside contains method this will return reference to same object as held in a reference variable.
Since you ware able to use this in for-each it means that contains method is placed in class which implements Iterable<E> interface because for-each can iterate only over:
arrays like String[] array = ...; for(String s : array){...}
instances of classes which implement Iterable<E> like List<String> where we can write for(String s : list){...}
To avoid this you can explicitly add to your method parameter of class which contains this method, like
public boolean contains(YourClass yc, Object o) {
//and use that parameter in loop instead of `this`
for (E x : yc)
if (x.equals(o))
return true;
return false;
}
but this means you would need to call such method in a way a.contains(a,x) so it needs to repeat a twice (not to mention it can allow us to pass other instance of our class than a like a.contains(b,x)).
To avoid this repetition we can make contains method static which will allow to invoke it via YourClass.contains(a,x). But this way we need to resign from one of basic OOP concepts - polymorphism - since it doesn't work with static methods.
Compiler solves it using first solution, so it compiles our methods like they would be written (and we actually CAN write methods that way) as
public boolean contains(YourClass this, Object o) {
// ^^^^^^^^^^^^^^
...
}
Then when we write a.contains(x) it is compiled as if we would invoke a.contains(a,x).
this is a object of the class that contains your contains() method. It refers to the object of that class for which the method is executed.
Putting it after the : of an enhanced for loop means that the class that contains this method must implement Iterable<E>, since the enhanced for loop can be used to iterate over either arrays or instances of classes that implement the Iterable interface. This means your class is able to iterate over some collection of E elements. E is probably a generic type parameter`.
In order to write your method without this, you would have to supply a reference to some alternative object that implements Iterable<E>, but I don't see the point of doing that.
What exactly means this in this code?
It is always a reference to the current instance. I assume your class implements the Iterable<T> interface and overrides the Iterator<T> iterator() method from it.
The loop is just a syntax sugar for the enhanced for statement. According to the specification (§14.14.2.):
for ({VariableModifier} UnannType VariableDeclaratorId : Expression)
Statement
The type of the Expression must be Iterable or an array type (§10.1), or a compile-time error occurs.
If the type of Expression is a subtype of Iterable, then the translation is as follows.
If the type of Expression is a subtype of Iterable<X> for some type argument X, then let I be the type java.util.Iterator<X>; otherwise, let I be the raw type Iterator.
The enhanced for statement is equivalent to a basic for statement of the form:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
{VariableModifier} TargetType Identifier = (TargetType) #i.next();
Statement
}
Usually, a class implements the Iterable to provide to an API user the ability of being allowed to iterate over the internal collection hiding the actual implementation.
Can I write it without this and how?
Use the logic you have written for the inner iterator.
Use the implementation of the underlying collection (if it's and it suits).
Choose one of the options mentioned above and rewrite into a standard for.
Keyword this is just a reference to the current object.
Here is a example how can be this used:
public class Person {
public final String name;
public Person(String name) {
// name = name;
// which one is an argument, and which one is class field?
// by default, both are reference on argument
// using "this" to access class field
this.name = name;
}
public void copyFields(Person other) {
// current object's reference is the same as other object reference
// in other words "this" and "other" are the same instances
// example:
// Person p1 = new Person("a");
// Person p2 = p1; // p2 is now pointing on the same memory address
// // as p1, so both are pointing on the same object
// // stored in memory.
// p1.copyFields(p2);
if (this == other) { // copying from self? useless...
return;
}
this.name = other.name;
}
}
Anything that implements Iterable interface has method which returns Iterator instance, which is implicitly used by foreach loop to iterate over items hold by object. Iterator
has methods hasNext() which returns true, if there is another object
in iterable container, relative to current position, and next() which returns
next object or throws NoSuchElementException if there is no next object (last invokation of hasNext() has returned false).
Here is a simple example of Iterable implementation with contains methods:
public class Customer extends Person implements Iterable<Item> {
private final List<Item> list = new LinkedList<>();
public final String name;
public Customer(String name) {
this.name = name;
}
public void add(Item item) {
list.add(item);
}
// implementing iterable interface
#Override
public Iterator<Item> iterator() {
return list.iterator();
}
// some contains implementations
public boolean contains1() {
for (Item item : this) { // customer implements Iterable = OK
if (o.equals(item)) {
return true;
}
}
return false;
}
public boolean contains2() {
for (Item item : list) { // list implements Iterable = OK
if (o.equals(item)) {
return true;
}
}
return false;
}
public boolean contains3(Object o) {
for (Iterator<Item> iter = iterator(); iter.hasNext(); ) {
Item item = iter.next();
if (o.equals(item)) {
return true;
}
}
return false;
}
public boolean contains4(Object o) {
for (Iterator<Item> iter = list.iterator(); iter.hasNext(); ) {
Item item = iter.next();
if (o.equals(item)) {
return true;
}
}
return false;
}
public boolean contains5(Object o) {
Iterator<Item> iter = iterator();
while (iter.hasNext()) {
Item item = iter.next();
if (o.equals(item)) {
return true;
}
}
return false;
}
public boolean contains6(Object o) {
Iterator<Item> iter = list.iterator();
while (iter.hasNext()) {
Item item = iter.next();
if (o.equals(item)) {
return true;
}
}
return false;
}
public boolean contains7(Object o) {
return list.contains(o);
}
}
Methods are defined in classes, not in objects.
But they are (generally) invoked from objects.
Methods - as they are defined in classes - don't know in advance which object will call them.
So there is a mechanism (implemented by a hidden parameter this) by which the object - when calling a method - secretively passes the address of itself to parameter this.
(In other programming languages may be used other names, as Me or self.)
I would put it in points for you
When we create a new instance of a class then the non static methods and non static member fields are part of it. We access these methods and fields using . operator.
All the non static method or member fields has access to this. The this keyword simply is a reference to the current object upon which that method is executed upon.
Any class which implements Iterable interface can be used with enhanced For-Loop.
Enhanced for loop uses a syntax
for (Object object : objectOfIterableType)
If the class implementing Iterable interface is parametized, suppose its E. then its what you have to in your code.
for (E x : this)
It means current class has the behaviour of being iterable and can be iterated on the collection of items it holds. Above statement will be executed for each item in the collection of items of type E represented by by the current object referred by this keyword. In each iteration x will represent an item from those contained items.

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 :-)

Extending ArrayList and Creating new methods

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

Java: Set<E> collection, where items are identified by its class

I need Set collection, where its items will be identified by items class. Something like ReferenceIdentityMap from Appache Collections, but on class scope i.e. two different instances of same class must be identified as same in this collection.
You know, it is a violation of equals()/hashCode() identity principle but in occasional use it makes sense.
I have done this in simple class backing with Map<Class<? extends E>, E>, but due to simplicity it doesn't implement Set<E>. There may be a more elegant solution, decorator of any Set<E> would be great.
Is there any implementation of such collection there (Apache/Google/something/... Collections)?
You wish to override the meaning of equals() / hashCode() for your set members. The cleanest way to do this, I imagine, is to use a wrapper class:
class Wrapper<E> {
private final E item;
Wrapper(E item) {
this.item = item;
}
E getItem() {
return item;
}
public boolean equals(Object o) {
if (!(o instanceof Wrapper)) {
return false;
}
return getClass().equals(o.getClass());
}
public int hashCode() {
return getClass().hashCode();
}
}
You would create a Set<Wrapper<E>> then.
How about extending HashSet and overriding just the add(..) method, putting object.getClass() instead of the object itself in an inner Set<Class<? extends E>>, and if it succeeds, adding the item itself. Something like
public class ClassSet<E> extends HashSet<E> {
private Set<Class<? extends E>> classSet = new HashSet<Class<? extends E>>();
#Override
public boolean add(E element) {
if (classSet.add((Class<E>) element.getClass())) {
return super.add(element); // this actually should always return true
}
return false;
}
}
You can create a Comparator class and construct your set with it in mind. The only condition you must not violate is that for every two elements you try to add, compare(e1, e2) should not throw a ClassCastException - which means that every two members you would try to insert should be comparable.
The comparator class itself should look only at the objects' classes, so it will be safe.
Check out the constructor here.

Categories