Alternative to instanceof approach in this case - java

Hello I'm wondering what would be some more elegant alternatives to something like this:
class Base...
class A extends Base...
class B extends Base...
//iterator of colection containing mixed As and Bs i want to remowe Bs and do omething with As
while(iterator.hasNext()) {
Base next = iterator.next();
if(next instanceof A) // do something
if(next instanceof B)
iterator.remove();
}
Sow what are the alternatives...
Thank you for advices.
edit: Base class may have many subclasses not just two and their numbers may grow in time

You can create methods in Base and override them in A and B.
For example:
class Base{
public boolean shouldRemove(){
return false;
}
public void doSomething(){
}
}
class A extends Base{
#Override
public void doSomething() {
}
}
class B extends Base{
#Override
public boolean shouldRemove() {
return true;
}
}
and then you don't need know what class the object is an instance of:
while(iterator.hasNext()) {
Base next = iterator.next();
if(next.shouldRemove()){
iterator.remove();
}
else{
next.doSomething();
}
}

Do you really need to remove them from the list? Why don't you just have the method to do something in the Base class (doing nothing) and then just override it do to what you want on class A.
class Base{
public void doSomething(){
}
}
class A extends Base{
#Override
public void doSomething(){
// do something
}
}
Then you could just iterate over the list and calling the method doSomething on all objects.
for(Base base : list) {
base.doSomething();
}
This way only the classes that have overridden the doSomething() method will actually do something. All the other classes will just execute the dummy implementation in the Base class.
If Base was an abstract class you could declare the doSomething() as abstract and have the extending classes implement it. With this approach all classes would have to implement the method and classes for which you don't want any computation to be performed you would just provide a dummy implementation of that method. Alternatively you could even create an interface with the doSomething() method and have (which could even be a better decision) and have the Base class implement it, given that only the extending classes would actually implement the method.

instanceof is a good way to filter objects by type - and that's what you want to do. You have a mixed collection and so you need some kind of filter, either filter the input (store nothing but As) or filter the output (process nothing but As).
If you just don't like "instanceof", you could use an enum to specify the type and add a final method to get the type at Base:
enum Type { ATYPE, BTYPE };
public Base {
final private Type type;
public Base(Type type) { this.type = type; }
public Type getType() { return type; }
// ...
}
public A {
public A() { super(Type.ATYPE); }
}
while(iterator.hasNext()) {
Base next = iterator.next();
switch (next.getType) {
case ATYPE: // do something and break
case BTYPE: iterator.remove(next); break;
}
}

i think is very short and clear solution and has no alternatives (without code growing),
just add else if instead of if in second case
Also you can split code on function calls, and if statement will not be huge
Another solution is to create Map of delegates that will be called. Like this:
interface ISimpleDelegate{ void doSomeLogic(Base b) }
`Map delegates = new HashMap();
After this add your logic as anonymous classes that realizes ISimpleDelegate.
delegates.put(A.class, new ISimpleDelegate() { //write your logic here });
I hope that the idea is clear
And in your loop you just call delegates:
while(iterator.hasNext()) {
Base next = iterator.next();
delegates.get(next.getClass()).doSomeLogic(next);
}

In general, a nice solution to avoid instanceof is to use the so-called visitor pattern.
For this pattern, you need an additional interface (the Visitor), an implementation of it that contains the code you want to execute and an additional method in all classes of your hierarchy, so this might be overkill in small cases (but it is very handy if there is not only A and B, but more types).
In your case it would look like this:
interface Visitor {
void visit(A a);
void visit(B b);
}
class Base {
abstract accept(Visitor v);
}
class A extends Base {
accept(Visitor v) {
v.visit(this);
}
}
class B extends Base {
accept(Visitor v) {
v.visit(this);
}
}
class MyVisitor implements Visitor {
visit(A a) {
doSomethingWithA(a);
}
visit(B b) {
doSomethingWithB(b);
}
}
It is used like this:
MyVisitor v = new MyVisitor();
while(iterator.hasNext()) {
Base next = iterator.next();
next.accept(v);
}
An advantage is that you have to write most of the code only once. If you want to do other things with A and B in another place of your program, just write another implementation of Visitor. You don't need to modify Base, A and B as you would if you'd add doSomething() to these classes.
Edit:
If the number of sub-classes increases, you need to change all your existing implementations of Visitor. However, at least the compiler tells you about that. With instanceof you might end up forgetting a place where you need to add a handling clause. This can at most be detected at runtime, whereas the visitor pattern gives you compile-time safety.

Related

One class implemeting two interfaces java

i have one class implemeting two different interfaces ,example:
public interface SortList{
void Sort();
search();
delete();
}
public interface unSortedList{
search();
delete();
}
class List implements ordenedList,unordenedList{}
I wanted to switch between ordened interface or not ordened list,thank you for your help.
You have to make 2 different class like OrderedList and UnorderedList. Implements are just a guarantee you have implemented those mehtots. So you have to make a switch case or if else in your methods or you have to make two different class.
I don't know what meaning you put behind "Ordened" and "UnOrdened", and if it makes sens to have a class implementing both, but anyway, here is an example on how you can use multiple implementations of interfaces, trying to keep up with your stuff.
I suppose by ordered the Java meaning as explained here, which is not sorted.
Let's say an Ordered interface gives the possibility to access some object (of type T) by index and to search or find for a given object:
public interface Ordered<T> {
T getNth(int i);
T find(T o);
}
Let's say an UnOrdered interface provides only the way to find an object:
public interface UnOrdered<T> {
T find(T o);
}
Now we can defined a class that implements both interfaces:
public class MyList<T> implements Ordered<T>, UnOrdered<T> {
List<T> theList;
public MyList(T...a) {
theList = Arrays.asList(a);
}
// The list of objects are neither sorted nor hashed.
// Only way to find an object is to iterate through the list
public T find(T o) {
for (T e : theList) {
if (e.equals(o)) {
return e;
}
}
return null;
}
public T getNth(int i) {
return theList.get(i);
}
}
public static void main(String[] args) {
MyList<Integer> mylist = new MyList<>(2,8,6,1,7,3,5,9,10,4);
System.out.println(mylist.getNth(3));
// => print 1
System.out.println(mylist.find(3));
// => print 3
System.out.println(mylist.find(42));
// => print null
}
You could have done a better job in describing the problem and what you are trying to solve for, assuming that I understood the problem, you can achieve this with Java 8 Default methods here is how
public interface UrdenedList{
void ordenate();
default T search(){
// default implementation here
}
default void delete(){
// default implementation here
}
}
public interface UnordenedList{
default T search(){
// default implementation here
}
default void delete(){
// default implementation here
}
}
I wanted to switch between ordened interface or not ordened list,thank
you for your help.
class List implements OrdenedList,UnordenedList{
void ordenate(){
// implementation here
}
T search(){
if(condition)
return OrdenedList.search();
else
return UnordenedList.search();
}
}
void delete(){
if(condition)
OrdenedList.delete();
else
UnordenedList.delete();
}
}
Notice Resolving conflicts by Explicitly choosing to call methods from interfaces OrdenedList, and OrdenedList

Calling ungeneric methods from generic method in java

Consider the following:
public class Doer {
public static void doStuff(A a) {
System.out.println("a");
}
public static void doStuff(B b) {
System.out.println("b");
}
}
Where B extends A
And a generic class like this:
public class NewClass<T extends A> {
public void doSomething(T entity) {
Doer.doStuff(entity);
}
}
If I call this method as follows it prints "a"
new NewClass<B>().doSomething(new B());
How do I get it to print "b" ?
Thanks in advance
Edit: A dirty solution is to change
Doer.doStuff(entity);
to
if(entity instanceof B){
Doer.doStuff((B) entity);
}else {
Doer.doStuff(entity);
}
But I'm looking for a solution that does not use instanceof and so that I don't have to add an extra if (C intance of A) ... to NewClass when I make a new Class extending A
See these questions for answers: Java Generic / Type Dispatch Question, How does Java method dispatch work with Generics and abstract classes?
Basically, you have these options:
define doStuff as an abstract method on A
try the Visitor pattern
if possible, use a language (e.g. Xtend) that supports dynamic dispatch
Java doesn't do dynamic binding based on the argument type. The actual method that is invoked is determined at compile time. So in case of a generic type, the method with Object as the parameter type will be invoked.
You could work around this by checking the type with instanceof, but the puristic way of handling this is to leverage polymorphism and using Double Dispatch. But that is not always an option, since it tightly couples your calling class and your argument class together.
I think that in that case you're forced to actually determine entity's type and cast it, as your function doSomething just infers that entity inherits from A.
Basically you could do:
public void doSomething(T entity) {
if (entity instanceof B) {
Doer.doStuff((B) entity);
}
else {
Doer.doStuff(entity);
}
}
NewClass would have to have two methods also, or you could do something like this:
public class NewClass<T extends A> {
public void doSomething(T entity) {
if(entity instanceof B){
Doer.doStuff((B)entity);
}else if(entity instanceof A){
Doer.doStuff((A)entity);
}
}
}

Overloading / generics in Java

I want to run certain tests in Lists. The Lists can contain entirely different classes.
I have one method to check the consistency of the list - not null, not empty, no more than x elements. This is common to all the lists. Then I want to test each of the objects, using overloading.
The idea would be something like:
public static <T> void check(List<T> list) {
//do general checks
for (T element : list) {
check(element);
}
}
and then
public static void check(SomeType element) {...}
public static void check(SomeOtherType element) {...}
But I also had to add a method like this:
public static void check(T element) {...}
And this was called at runtime - not my other methods with the specific classes. Although the class was exactly the same. I'm evidently missing some generics understanding.
Now if I don't use the general method at all and try to solve it this way:
public static void check(List<SomeType> list) {...}
public static void check(List<SomeOtherType> list) {...}
Compiler error - "Method check(List) has the same erasure check(List) as another method..."
So is there any elegant solution for this? I could just use different method names but would like to know how it's possible without that.
Thanks!
This isn't something about generics that you're missing. Java does not have double dispatch. The call to check must be resolved at compile-time, and check(T) is the only match since the compiler can't tell if T is SomeType or SomeOtherType in a given scenario. It needs to choose one method to call that will work for all possible Ts.
This is sometimes solved using the visitor pattern.
The problem should be solved by the caller. When it instanciate your class with a concrete type for T, it should also pass an instance of Checker<T> with the same concrete type:
public class SomeClass<T> {
private List<T> list;
private Checker<T> checker;
public SomeClass(Checker<T> checker) {
this.checker = checker;
}
public void check() {
checker.check(list);
}
}
public interface Checker<T> {
public void check(List<T> list);
}
...
SomeClass<Foo> someClass = new SomeClass<Foo>(new Checker<Foo>() {
#Override
public void check(List<Foo> list) {
// do whatever you want here
}
});
You can use instanceof to dispatch:
public static <T> void check(List<T> list) {
for (T element : list) {
check(element);
}
}
public static void check(T t) {
if (t instanceof SomeType) {
SomeType someType = (SomeType) t;
// code for SomeType ...
} else if (t instanceof OtherType) {
OtherType otherType = (OtherType) t;
// code for OtherType ...
} else {
// we got a type that we don't have a method for
}
}
With generics, the type parameter is actually erased during compilation, and the list object don't know anything about the static type of the object it contains. Since it doesn't know it, it can not use overloading to call methods with different parameters, because Java doesn't support multiple dispatch.
You have then three choices:
Make your objects implement a Checked interface with a check method that does the check logic. Downside is that the check logic is now dispersed in several places and it is not practical if you have objects of classes you don't have control of.
Use instanceof to call explicitly the check methods according to the dynamic type of the object. Downside is you potentially end up with a big if/else block a bit harder to maintain.
Implement the visitor pattern. Downside is that you have to change the object classes too, but the check logic stay in a single place.
Since the type of the variable is lost in check(List<T> list) you have two options:
1. Do different things by checking runtime type
check(T element) {
if (element.getClass().equals(SomeType.class)) {
check((SomeType) element);
} elseif (element.getClass().equals(SomeOtherType.class)) {
check((SomeOtherType) element);
}
This can be made a little more sophisticated, for example by wrapping each check in a Callable and using a Map<Class, Callable>
This is similar to visitor pattern.
2. Calling a virtual method on the element to be checked itself
If the checking logic can be pushed to the object to be checked itself (this is not necessarily a bad thing) then you don't need to check types:
interface Checkable { void check(); }
class SomeType implements Checkable { .... }
class SomeOtherType implements Checkable { .... }
Then:
public static <T extends Checkable> void check(List<T> list) {
for (T element : list) {
element.check();
}
}
These are the only two options, any implementation has to be a variation on one of these

avoiding instanceof

I have a set of POJOs with a common superclass. Those are stored in a two-dimensional array of type superclass. Now, I want to obtain an object from the array and use methods of the subclass. This means I have to cast them to the subclass. Is there a way to do this without using instanceof?
Update: As a concrete example: http://obviam.net/index.php/the-mvc-pattern-tutorial-building-games/ See: "Add new actions (attack) when an enemy is clicked"
Yes - you can do it by inverting the flow: instead of your code doing something when the instance of the base class is of a specific type, pass an action item to the object, and let the object decide whether to perform it or not. This is the basic trick behind the Visitor Pattern.
interface DoSomething {
void act();
}
abstract class AbstractBaseClass {
abstract void performAction(DoSomething ds);
}
class FirstSubclass extends AbstractBaseClass {
public void performAction(DoSomething ds) {
ds.act();
}
}
class SecondSubclass extends AbstractBaseClass {
public void performAction(DoSomething ds) {
// Do nothing
}
}
AbstractBaseClass array[] = new AbstractBaseClass[] {
new FirstSubclass()
, new FirstSubclass()
, new SecondSubclass()
, new FirstSubclass()
, new SecondSubclass()
};
for (AbstractBaseClass b : array) {
b.performAction(new DoSomething() {
public void act() {
System.out.println("Hello, I'm here!");
}
});
}
If you know they're of the subclass type, then just cast them directly without an instanceof check.
But putting them in a superclass-typed array is telling the compiler to discard the information that they're actually of the subclass type. Either your superclass should expose those methods (perhaps as abstract), or your array should be of the subclass type (so you're not telling the compiler to forget the actual type of the objects), or you'll have to suck it up and do the cast (possibly with the instanceof test).
The only other notable alternative is that you might experiment with the visitor pattern, which passes an action to the object and lets the object decide what to do with it. That lets you override classes to ignore or perform the actions based on their runtime type.
You can try to use the Visitor design pattern.
http://en.wikipedia.org/wiki/Visitor_pattern
You have to ask yourself, why do you need to know their type, maybe this can be replaced with the use of an abstract method in the super class, that every one of them can implement according the desired result.
abstract class A{
abstract void visit();
}
class B extends A{
void visit() { print("B"); }
}
class C extends A {
void visit() { print("C"); }
}
I would avoid casting them in the first place.
Really think about what you're trying to do, and if they should be in the same collection like that.
If you have something like this
for(MyObj o : array) {
if(o instanceof A) {
((A)o).doA();
}
if(o instanceof B) {
((B)o).doB();
}
}
consider this instead
abstract class MyObj {
abstract void doIt();
}
class A {
void doIt() { doA(); }
}
class B {
void doIt() { doB(); }
}
Expose the method in the superclass, and then use overriding. Provide an empty implementation in the base class so that subclasses can ignore the action if needed.

safe cast by a subclass type id in java

I have a base Entity class:
public class Entity
{
abstract int getTypeID();
}
The method int getTypeID() returns a number that is unique to that class:
public class OneEntity extends Entity
{
int getTypeID()
{
return 1; // Actually defined in a constants class
}
}
Now I want to be able to safely cast it and assign it.
I can do it this way:
public void castTheEntityAndDoSomething(Entity ent)
{
if (isType(ent, 1)) // this is the 1 from the OneEntity class
{
OneEntity oneEnt = (OneEntity)ent;
// ... and then do something
}
}
public bool isType(Entity ent, int type)
{
return ent.getTypeID() == type;
}
But what I'd like to do is combine the cast and the type check in one line.
Something like:
if (OneEntity oneEnt = entityCast(ent, 1))
{
// use a method specific to the OneEntity class
}
Is this possible? What does the method look like?
It would be even better if I could use the subclass name as an argument of the safe casting method.
EDIT:
So I've written this method to avoid the type id etc. etc.
#SuppressWarnings("unchecked")
public static <T extends Entity> T castEntity(Entity ent)
{
if (ent instanceof T)
{
return (T)ent;
}
return null;
}
But it has this error:
Cannot perform instanceof check against type parameter T. Use instead its erasure Entity since generic type information will be erased at runtime
What do I need to do to fix this compile error? Is this even going in the right direction?
In case you have defined this typeId for the sole purpose of casting, then please don't do that and use instanceof operator instead.
Then you just need to do something like this,
if (ent instanceof EntityOne) {
OneEntity oneEntity = (OneEntity) ent;
// do whatever
}
Now, taking your example here,
if (Entity oneEnt = entityCast(ent, 1))
{
// do something with oneEnt
}
Suppose this if statement of yours work and your entityCast() method return OneEntity. Don't you think you are again getting that returned value in type Entity. Hence spoiling the whole purpose.
So, please explain what are you trying to do exactly.
If you implement an interface which defines the methods you want to call on them from the "do something" blocks and implement that inteface in all your derived entiries, your have solved problem by using polymorphism.
You might want to rethink your architecture.
First of all maybe you should not have a typeID field in the class.
You should rely on the "power" of inheritance and/or interfaces instead.
// Entity.java
public interface Entity { abstract public void doSomeThing(); }
// EntityType1.java
public class OneEntity extends Entity {
#Override
public void doSomeThing() {
// do something specific for entity type 1
}
}
// EntityType2.java
public class TwoEntity extends Entity {
#Override
public void doSomeThing() {
// do something specific for entity type 2
}
}
// Main.java
public static void main(String[] args) {
Entity e1 = new EntityType1();
Entity e2 = new EntityType2();
e1.doSomeThing();
e2.doSomeThing();
}
You should encapsulate the different behavior in the implementation classes.
If you think you have good reasons to detach the behavior from the entities you would better use this same logic in a hierarchy of external processing classes (maybe with a simple factory on top) and use "instanceof" in the factory method.
I suppose that you could do this:
OneEntity oneEnt;
if (isType(ent, 1) && (oneEnt = (OneEntity) ent) != null) {
// ... and then do something
}
... or the equivalent with instanceof instead of your icky isType method ...
Or you could define a method called oneEntityOrNull as follows:
public OneEntity oneEntityOrNull(Entity ent) {
return ent instanceof OneEntity ? (OneEntity) ent : null;
}
and then
OneEntity oneEnt;
if ((oneEnt = oneEntityOrNull(ent)) != null) {
// ... and then do something
}
but IMO both of these are a BAD IDEA since the code is harder to understand than the original.

Categories