Is it okay to use the instanceof operator to implement two parallel hierarchies of functions and arguments to those?
Is it bad practice to use the instanceof operator in the following context?
public interface IWriter {
public abstract void write(Dto dto);
}
public abstract class Dto {
private long id;
public void setId(long id) {this.id = id;}
public long getId() {return id;}
}
public class DtoA extends Dto {
...
}
public class DtoB extends Dto {
...
}
public class MyWriterA implements IWriter {
@Override
public void writer(Dto dto) {
if (!(dto instanceof DtoA))
return;
...
}
}
public class MyWriterB implements IWriter {
@Override
public void writer(Dto dto) {
if (!开发者_JAVA百科(dto instanceof DtoB))
return;
...
}
}
There is a lot of myths about the use of that operator and I am not completely sure that what I am doing is not bunk.
I have a lot of different writer implementations which I want to combine in one interface. The problem is not every DTO is applicable for every writer. In my actual code there is a deep hierarchy of DTOs, which extend DtoA and DtoB, and either the hierarchy branch of DtoA or DtoB is applicable for a writer, but only in a few cases both.
Should I avoid using the abstract class Dto as argument for the abstract write(Dto dto)
method?
EDIT: Please read the comments on the accepted answer.
Sometimes there's no getting around using instanceof
- there is no need to feel shame.
Typing IWriter may help:
public interface IWriter<T extends Dto> {
public abstract void write(T dto);
}
then
public class MyWriterA implements IWriter<DtoA> {
@Override
public void writer(DtoA dto) {
// No need for instanceof, because it can't be anything else
...
}
}
Perhaps a combination of such typing and Brian Agnew's worthy answer would do the trick.
How is the code calling the IWriter? Presumably you've got to determine the type up there too? In which case you already know what kind of writer you need. You're already dispatching on the basis of Type.
Your writers are not really substitutable WriterA only does As and so on. In which case you're not gaining anything by claiming they are in an inheritance hierarchy.
Have you looked at double-dispatch or the Visitor pattern ?
Essentially your Writer and DTO objects would mediate to call the correct methods e.g.
public void writer(Dto dto) {
dto.doSomething(writer);
}
and the doSomething()
method called would depend on the type of the Dto
. Your Dto
object would implement a version for MyWriterA/B
.
Using instanceOf
isn't unavoidable, but is often a design smell, indicating that something isn't right, or could be done better.
精彩评论