I am currently working on a piece of code, in which behavioral decisions are made based on whether the request object is of a certain sub-type, like so:
class Request{
public void doThing(){
System.out.println("doing Thing...");
}
}
class SpecialRequest extends Request{
...
}
void method(Request request){
if(request instanceof SpecialRequest){
System.out.println("is special...");
}
request.doThing();
}
SpecialRequest in this case has nothing else implemented, that would distinguish it from a normal Request. My question now is, if there are any advantages or disadvantages from using this style instead:
class Request{
...
public boolean isSpecial(){
return special;
}
public void doThing(){
System.out.println("doing Thing...");
}
}
void method(Request request){
if(request.isSpecial()){
System.out.println("is special...");
}
request.doThing();
}
I understand how the second Method could get very convoluted the more decisions I want to make. But I am also interested in how these two approaches compare performance wise.
Thanks in advance.
EDIT: First of all thanks for the quick response. I should have probably mentioned, that my Request and my SpecialRequest are supposed to merely carrying data, and not contain any logic. That's just how the whole software is designed. My method just consumed the request and is supposed to behave differently based on whether the request is special or not. "instanceof" just seems like dirty code to me, but the boolean also doesn't seem quite right. Any advice is still welcome.
The clear advantage of using a method is that it's not closely tied to a particular type. You could add a new class VerySpecialRequest which also provides this behaviour, and you wouldn't necessarily need to extend SpecialRequest in order to do that.
However, the more pressing issue here is that you have explicit conditional branching at all. The object should be responsible for determining whether there's any additional behaviour required, and then the nasty conditional logic goes away altogether:
class Request{
public void doThing(){
System.out.println("doing Thing...");
}
}
class SpecialRequest extends Request{
#Override
public void doThing(){
super.doThing();
System.out.println("is special...");
}
}
You might also consider using the visitor pattern (https://en.wikipedia.org/wiki/Visitor_pattern), as it ensures type-safety and does not need the instanceof-check. Furthermore it is more obvious where you have to extend/ modify your code, when you create a new type of request (e.g. "VerySpecialRequest").
All you have to do is to create an interface with visit-methods for every type you want to execute special code, like this:
public interface RequestProcessor {
void visit(Request request);
void visit(SpecialRequest specialRequest);
}
The request classes need accept-methods that do nothing but calling the visitor with itself:
public class Request {
...
void accept(RequestProcessor requestProcessor) {
requestProcessor.visit(this);
}
}
Same for SpecialRequest:
public class SpecialRequest extends Request {
...
#Override
void accept(RequestProcessor requestProcessor) {
requestProcessor.visit(this);
}
}
Then you can simply implement your logic in a class that implements the interface (here as an anonymous class):
RequestProcessor requestProcessor = new RequestProcessor() {
#Override
public void visit(Request request) {
System.out.println("I'm a normal request");
}
#Override
public void visit(SpecialRequest specialRequest) {
System.out.println("I'm a special request");
}
};
Request request = new Request();
request.accept(requestProcessor);
SpecialRequest specialRequest = new SpecialRequest();
specialRequest.accept(requestProcessor);
As you can see there are no more instance-of checks. Another advantage of this is that you can "process requests" even if they are no direct subclass of 'Request' - all you have to do is to extract the accept-method in its own interface. Hope this helps.
1.- insteadof, is a type comparison operator because it compares the instance with type. It returns either true or false. If you apply the instanceof operator with any variable that has null value, it returns false.
2.- isSpecial(), is a method of your own. You can do what ever you want in that piece of code, so the comparisson in that case is up to you.
3.- You have to be aware that when you use instanceof, the comparison also do a class cast of the variable in mention, so if that can't be done, you should get a compile time error. see this : compile time error with instanceof
4.- if you use this operator to much, you should check it, because that's a signal of some bad code. For more details see this: use of instaceof
Related
I'm implementing a service class having a method like this:
public void makeSomething() {
// some logic...
// [optional logic]
// some other logic...
}
This is a concrete class and it can be instantiated and used "as is", but I somethimes need to extend it and override the makeSomething() method adding some additional logic (in the middle). I mean: I need to use the same logic in parent method, but i need to extend logic before return.
My first idea was to add an "optional" method in the middle of the original method:
public void makeSomething() {
// some logic...
optionalOperation();
// some other logic...
}
and eventually override the optionalOperation() method in extending classes. But I don't like this: I will have an empty method doing nothing in my original class...
So, is there a better way to design my method? Is there some design pattern addressing my issue?
The design pattern is called Template method and it works exactly the way you don't like, I'm afraid.
For example, Spring's code is full of such empty protected methods waiting for you to add something custom into them.
i can think of 2 ways:
inheritance and common 'lifecycle' aka Template Method. it's very problematic to maintain when it's in the middle of your business logic
strategy pattern. try to refactor and pass strategy to the method or object owning this method. if you can use any functional language you can take it to the extreme and instead of passing strategy use a function composition: define 'makeSomething' as a function of other functions. and one of 'makeSomething' will contain also 'optionalOperation' in it's definition. but it may require really heavy refactoring
A simple solution would be this:
public class AClass {
public void makeSomething() {
someLogic();
someOtherLogic();
}
protected void someLogic() {
System.out.println("some logic");
}
protected void someOtherLogic() {
System.out.println("some other logic");
}
}
public class AnEnhancedClass extends AClass {
#Override
public void makeSomething() {
someLogic();
System.out.println("optional operation");
someOtherLogic();
}
}
I try to follow this Stackoverflow post but it was not helping my purpose what I wanted to achieve. I want to know is it achievable in Java. Here is the problem statement. I tried to look into Java reflection, Haskel Either, etc. but it endup having two different objects.
I have two type of objects.
com.mobilesecuritycard.openmobileapi.Session msc_session;
org.simalliance.openmobileapi.Session sim_session
I want to have a method which accepts any of the two objects given above.
For example
public void runOperation(Object activeSession) {
activeSession.openLogicalChannel(APPLET_AID);
-- do the rest of operations ---
}
I want to use that function as given below
if(isSetSIMSessionTrue()){
Log.i(LOG_TAG, "Using SIM Session as its True");
sim_session = getSim_session();
runOperation((org.simalliance.openmobileapi.Session) sim_session);
} else{
Log.i(LOG_TAG, "Using MSC Session as its false");
msc_session = getMSCSession();
runOperation((com.mobilesecuritycard.openmobileapi.Session) msc_session);
}
I can even receive correct object class using
String classNameToBeLoaded = activeSession.getClass().getName();
But still not able to get object properties to activeSession object.
Is there any way to pass either of the session object to the runOperation method and only use activeSession for doing rest of the operation. As both objects has same methods and functionality but access different secure element on a android device. So, I do not want to write two different runOperation() method for the different objects. To be more precise, is it possible to cast an object type to another object. I am not sure about this. Any pointers or help will be grateful. I hope, I made my point clear what I want to achieve.
PS: please ignore syntax as I am just providing some code snippets to make my question clear.
You should be able to do this with reflection or even just instanceof, but why? Why not use overloading? Define two methods:
public void runOperation(com.mobilesecuritycard.openmobileapi.Session session) {
}
public void runOperation(org.simalliance.openmobileapi.Session session) {
}
If the goal is to reduce code duplication, then use a single method but have it take the least common ancestor superclass of the two types of sessions, which is hopefully not Object:
public void runOperation(SessionSuperclass session) {
// do something that can work with any type of session
doSomethingMoreSpecific(session);
}
And if necessary, implement two versions of doSomethingMoreSpecific(). That would be the object-oriented way of doing things, not instanceof or reflection.
if(activeSession instanceof com.mobilesecuritycard.openmobileapi.Session) {
// some stuff
} else if(activeSession instanceof org.simalliance.openmobileapi.Session) {
// some other stuff
}
You can do this check in your runOperation().
if(activeSession instanceof org.simalliance.openmobileapi.Session){
// Type 1
}
else if(activeSession instanceof com.mobilesecuritycard.openmobileapi.Session){
// Type 2
}
One solution that springs to mind is to have both of the objects implement a common interface.
For example
public interface ObjectIF
{
public void doSomething();
}
Have some classes that implement the interface:
public class ClassOne implements ObjectIF
{
public void doSomething() { // Code }
}
public class ClassTwo implements ObjectIF
{
public void doSomething() { // Code }
}
Now with your method you can do something like this:
public void doSomethingWithObject(ObjectIF object)
{
// Provided an object implements the interface, it can be passed here.
object.doSomething();
}
is it possible to cast an object type to another object?
Yes, you can cast.
You can check and cast:
if(activeSession instanceof org.simalliance.openmobileapi.Session){
org.simalliance.openmobileapi.Session mySession = (org.simalliance.openmobileapi.Session) activeSession
}
else if(activeSession instanceof com.mobilesecuritycard.openmobileapi.Session) {
com.mobilesecuritycard.openmobileapi.Session mySession = (com.mobilesecuritycard.openmobileapi.Session) activeSession
}
Let's say I have a manufacturing scheduling system, which is made up of four parts:
There are factories that can manufacture a certain type of product and know if they are busy:
interface Factory<ProductType> {
void buildProduct(ProductType product);
boolean isBusy();
}
There is a set of different products, which (among other things) know in which factory they are built:
interface Product<ActualProductType extends Product<ActualProductType>> {
Factory<ActualProductType> getFactory();
}
Then there is an ordering system that can generate requests for products to be built:
interface OrderSystem {
Product<?> getNextProduct();
}
Finally, there's a dispatcher that grabs the orders and maintains a work-queue for each factory:
class Dispatcher {
Map<Factory<?>, Queue<Product<?>>> workQueues
= new HashMap<Factory<?>, Queue<Product<?>>>();
public void addNextOrder(OrderSystem orderSystem) {
Product<?> nextProduct = orderSystem.getNextProduct();
workQueues.get(nextProduct.getFactory()).add(nextProduct);
}
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy())
factory.buildProduct(workQueues.get(factory).poll());
}
}
Disclaimer: This code is merely an example and has several bugs (check if factory exists as a key in workQueues missing, ...) and is highly non-optimal (could iterate over entryset instead of keyset, ...)
Now the question:
The last line in the Dispatcher (factory.buildProduct(workqueues.get(factory).poll());) throws this compile-error:
The method buildProduct(capture#5-of ?) in the type Factory<capture#5-of ?> is not applicable for the arguments (Product<capture#7-of ?>)
I've been racking my brain over how to fix this in a type-safe way, but my Generics-skills have failed me here...
Changing it to the following, for example, doesn't help either:
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy()) {
Product<?> product = workQueues.get(factory).poll();
product.getFactory().buildProduct(product);
}
}
Even though in this case it should be clear that this is ok...
I guess I could add a "buildMe()" function to every Product that calls factory.buildProduct(this), but I have a hard time believing that this should be my most elegant solution.
Any ideas?
EDIT:
A quick example for an implementation of Product and Factory:
class Widget implements Product<Widget> {
public String color;
#Override
public Factory<Widget> getFactory() {
return WidgetFactory.INSTANCE;
}
}
class WidgetFactory implements Factory<Widget> {
static final INSTANCE = new WidgetFactory();
#Override
public void buildProduct(Widget product) {
// Build the widget of the given color (product.color)
}
#Override
public boolean isBusy() {
return false; // It's really quick to make this widget
}
}
Your code is weird.
Your problem is that you are passing A Product<?> to a method which expects a ProductType which is actually T.
Also I have no idea what Product is as you don't mention its definition in the OP.
You need to pass a Product<?> to work. I don't know where you will get it as I can not understand what you are trying to do with your code
Map<Factory<?>, Queue<Product<?>>> workQueues = new HashMap<Factory<?>, Queue<Product<?>>>();
// factory has the type "Factory of ?"
for (Factory<?> factory: workqueues.keySet())
// the queue is of type "Queue of Product of ?"
Queue<Product<?>> q = workqueues.get(factory);
// thus you put a "Product of ?" into a method that expects a "?"
// the compiler can't do anything with that.
factory.buildProduct(q.poll());
}
Got it! Thanks to meriton who answered this version of the question:
How to replace run-time instanceof check with compile-time generics validation
I need to baby-step the compiler through the product.getFactory().buildProduct(product)-part by doing this in a separate generic function. Here are the changes that I needed to make to the code to get it to work (what a mess):
Be more specific about the OrderSystem:
interface OrderSystem {
<ProductType extends Product<ProductType>> ProductType getNextProduct();
}
Define my own, more strongly typed queue to hold the products:
#SuppressWarnings("serial")
class MyQueue<T extends Product<T>> extends LinkedList<T> {};
And finally, changing the Dispatcher to this beast:
class Dispatcher {
Map<Factory<?>, MyQueue<?>> workQueues = new HashMap<Factory<?>, MyQueue<?>>();
#SuppressWarnings("unchecked")
public <ProductType extends Product<ProductType>> void addNextOrder(OrderSystem orderSystem) {
ProductType nextProduct = orderSystem.getNextProduct();
MyQueue<ProductType> myQueue = (MyQueue<ProductType>) workQueues.get(nextProduct.getFactory());
myQueue.add(nextProduct);
}
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy())
buildProduct(workQueues.get(factory).poll());
}
public <ProductType extends Product<ProductType>> void buildProduct(ProductType product) {
product.getFactory().buildProduct(product);
}
}
Notice all the generic functions, especially the last one. Also notice, that I can NOT inline this function back into my for loop as I did in the original question.
Also note, that the #SuppressWarnings("unchecked") annotation on the addNextOrder() function is needed for the typecast of the queue, not some Product object. Since I only call "add" on this queue, which, after compilation and type-erasure, stores all elements simply as objects, this should not result in any run-time casting exceptions, ever. (Please do correct me if this is wrong!)
Yesterday I asked this question, and the solution posted by #JB Nizet worked perfectly. However, that answer, as well as a few other answers/comments got me thinking in a different direction altogether.
Essentially, I have the following classes:
Load
HttpLoad extends Load
Target
HttpTarget extends Target
Controller
The Controller's job is to Target::fire() a Load, and doesn't care which Target is firing which Load:
// Inside Controller.java
Target target = getTarget();
Load load = getLoad();
target.fire(load);
However, I might some day write a FtpLoad extends Load, and I don't want to be able to fire a FtpLoad at an HttpTarget. So the essence of the above-referenced question was how do I do this, to which, the answer was generics.
However, as the answerer pointed out, this solution is a violation of the Liksov Substitution Principle. Other answerer/commenters seemed to indicate that what I was doing wasn't necessarily good OOP practices.
So now I'm asking: how do I expose an API so that the Controller can be Load- and Target-agnostic, but still enforce that the proper Load subclass is fired on the proper Target type, all without violating Liskov Substitution?
And, if this is impossible to do (without violating Liskov), then what is the normal approach to a problem like this? Thanks in advance!
If HttpTarget.fire allows any Load as parameter, it is its job to check if it can fire this Load. So either the Controller calls fire blindly, and fire checks if the given target can fire that kind of Load (with instanceof), or you include a function canFire in every target that implements this check and is called by the Controller.
The typing problem here is that HttpTarget is not a Liskov subtype of Target, because semantically it is attempting to strengthen the preconditions of Target#fire(Load) to require the Load be HttpLoad.
This can be trivially repaired by declaring Target#fire(Load) throws IncompatibleLoadException and having a default implementation that always throws, forcing Controller to deal with the fact that a mismatched Load can be passed in.
The easy way is to do some checking in your code to make sure the classes match up. You can use the instanceof keyword to check if it's the correct class.
Best is to implement abstract class or an interface and use instanceof as mentioned before.
With an abstract class:
public abstract class TargetLoad {
public abstract void fire(TargetLoad i);
}
public class Load extends TargetLoad {
#Override
public void fire(TargetLoad i) {
if (i instanceof Target) return;
// do fire stuff
}
}
public class Target extends TargetLoad {
#Override
public void fire(TargetLoad i) {
if (i instanceof Load) return;
// do fire stuff
}
}
with an interface:
public interface TargetLoad {
public void fire(TargetLoad i);
}
public class Load implements TargetLoad {
#Override
public void fire(TargetLoad i) {
if (i instanceof Target) return;
// do fire stuff
}
}
public class Target implements TargetLoad {
#Override
public void fire(TargetLoad i) {
if (i instanceof Load) return;
// do fire stuff
}
}
In your Controller you refer to your objects as TargetLoad
TargetLoad target = getTarget();
TargetLoad load = getLoad();
target.fire(load);
load.fire(target);
load.fire(load); //this will do nothing
target.fire(target); //this will do nothing
I strongly disagree with the slew of answers recommending to use instanceof. Well-written OOP code very rarely needs to use instanceof, and using instanceof will generally make your code awkward and difficult to maintain. As a general rule, avoid instanceof if at all possible.
The previous question you referred to provided a solution using generics. I'm not sure you left the generics code out of your question here; go back to your generic code. Now, add the following method to your driver.
private <L extends Load> void runSuite(TestSuite<L> suite) {
Target<L> target = testSuite.getTarget();
L load = testSuite.getLoad();
target.fire(load);
}
Sorry for the poor title, can't think of a succinct way of putting this..
I'm thinking of having a list of objects that will all be of a specific interface. Each of these objects may then implement further interfaces, but there is no guarantee which object will implement which. However, in a single loop, I wish to be able to call the methods of whatever their further sub-type may be.
Ie, 3 interfaces:
public interface IAnimal { ... }
public interface IEggLayer { public Egg layEgg(); }
public interface IMammal { public void sweat(); }
this would then be stored as
private List<IAnimal> animals= new ArrayList<IAnimal>();
so, instances added to the list could possibly also be of type IEggLayer or IMammal, which have completely unrelated methods.
My initial instinct would be to then do
for(IAnimal animal : animals) {
if(animal instanceof IEggLayer) {
egg = ((IEggLayer)animal).layEgg();
}
if(animal instance of IMammal) {
((IMammal)animal).sweat();
}
}
But I have always been told that type checking is a sign that the code should really be refactored.
Since it could be possible for a single object to do both [platypus, for example], meaning that a single doFunction() would not be suitable here, is it possible to avoid using type checking in this case, or is this an instance where type checking is classed as acceptable?
Is there possibly a design pattern catered to this?
I apologise for the contrived example as well...
[Ignore any syntax errors, please - it's only intended to be Java-like pseudocode]
I've added lvalue to the EggLayer use, to show that sometimes the return type is important
Clearly your IAnimal interface (or some extension thereof) needs a callAllMethods method that each implementer of the interface can code to polymorphically perform this task -- seems the only OO-sound approach!
But I have always been told that type checking is a sign that the code should really be refactored.
It is a sign that either class hierarchy or the code that uses it may need to be refactored or restructured. But often there will be no refactoring / restructuring that avoids the problem.
In this case, where you have methods that apply only to specific subtypes, the most promising refactor would be to have separate lists for the animals that are egg layers and the animals that sweat.
But if you cannot do that, you will need to do some type checking. Even the isEggLayer() / isMammal() involves a type check; e.g.
if (x.isEggLayer()) {
((IEggLayer) x).layEgg(); // type cast is required.
}
I suppose that you could hide the type check via an asEggLayer() method; e.g.
public IEggLayer asEggLayer() {
return ((IEggLayer) this);
}
or
// Not recommended ...
public IEggLayer asEggLayer() {
return (this instanceof IEggLayer) ? ((IEggLayer) this) : null;
}
But there is always a typecheck happening, and the possibility that it will fail. Furthermore, all of these attempts to hide the type checking entail adding "knowledge" of the subtypes to the supertype interface, which means that it needs to be changed as new subtypes are added.
in C#, you should be able to do this transparently.
foreach(IEggLayer egglayer in animals) {
egglayer.layEgg();
}
foreach(IMammal mammal in animals) {
mammal.sweat();
}
I think the way to think about this question is: What is the loop doing? The loop has a purpose and is trying to do something with those objects. That something can have a method on the IAnimal interface, and the implementations can sweat or lay eggs as needed.
In terms of your issue with the return value, you will be returning null, nothing you can do about that if you share the methods. It is not worth casting within a loop to avoid an extra return null; to satisfy the compiler. You can, however, make it more explicit using generics:
public interface IAnimal<R> {
public R generalMethod();
}
public interface IEggLayer extends IAnimal<Egg> {
public Egg generalMethod(); //not necessary, but the point is it works.
}
public interface IMammal extends IAnimal<Void> {
public Void generalMethod();
}
From your comment where you care about the return type, you can get the return type and dispatch it to a factory method which examines the type and returns something generic that is sublcassed to the specific type and act on that.
Why not have methods added to isAnimal:
public interface IAnimal {
bool isEggLayer();
bool isMammal();
}
Then you can loop through and just query this boolean each time.
Update:
If this was drawing an animal, then having a class that is completely enclosed is reasonable, you just call drawVehicle and it draws a corvette, cessna, motorcycle, whatever.
But, this seems to have a non-OOP architecture, so if the architecture of the application can't change then, since my original answer isn't well received, then it would seem that AOP would be the best choice.
If you put an annotation on each class, you can have
#IsEggLayer
#IsMammal
public class Platypus() implements EggLayer, Mammal {
...
}
This would then enable you to create aspects that pull out all the egglayers and do whatever operations need to be done.
You can also inject into the animal interfaces any additional classes to get this idea to work.
I will need to think about where to go from here, but I have a feeling this may be the best solution, if a redesign can't be done.
There are many ways of going about this. Exaclty which is most appropriate depends upon your context. I am going to suggest introducing an additional layer of indirection. This solves most problems. I prefer designs which avoid multiple inheritance of interface (if I were president of a language, I would forbid it).
I don't think layEggsOrSweatOrDoBothIfYoureWeirdOrNoneIfYouCant() is a great method to polute Animal with. So instead of adding each Animal directly to animals, wrap each in an individual wrapper. I say "wrapper" as a generic name - the random operation we are trying to perform doesn't make any sense.
private final List<AnimalWrapper> animals =
new ArrayList<AnimalWrapper>();
public void doStuff() {
for (AnimalWrapper animal : animals) {
animal.doStuff();
}
}
Then we need some way of adding the wrappers. Something like:
public void addPlatypus(final Platypus platypus) {
animals.add(new AnimalWrapper() { public void doYourStuff() {
platypus.sweat();
platypus.layEgg();
}});
}
If you try to write these wrappers without enough context you get into trouble. These require that the correct one is selected at call site. It could be done by overloading, but that has dangers.
/*** Poor context -> trouble ***/
public void addNormalMamal(final Mamal mamal) {
animals.add(new AnimalWrapper() { public void doYourStuff() {
mamal.sweat();
}});
}
public void addNormalEggLayer(final EggLayer eggLayer) {
animals.add(new AnimalWrapper() { public void doYourStuff() {
eggLayer.layEgg();
}});
}
public <T extends Mamal & EggLayer> void addMamalEggLayer(final T animal) {
animals.add(new AnimalWrapper() { public void doYourStuff() {
animal.sweat();
animal.layEgg();
}});
}