This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
I'm writing some code that recieves an object of known super-class ( but I don't know what subclass of that super it will be ) I then need to do different stuff with it dependent on its type. Write now my strategy looks something like this:
Obviously this is a huge pain in the butt. I wish I could just overload dosub() like this:
but of course, that doesn't compile because the compiler is looking for:
So my question is: Is there any better way of getting type dependent behavoir, given that all I know about the object is it's superClass? (I also know all possible subclasses of the object ... but of course the compiler doesn't know that I know that). thanks, joe p.s. This would be easy if I could use polymorphism and have the subs each contain their own implementation of doStuff(). Unfortunately I can't do that.
Why can't you do that? That is what you are SUPPOSED to do. Why use an object-oriented language if you can't use polymorphism?
"JavaRanch, where the deer and the Certified play" - David O'Meara
Joined: Feb 22, 2001
Agreed. The code is question is test code. The objects in question are production code. An executive decision has been made that production code is not to be changed to accomadate test code. It's dumb, but I'm stuck with it.
Joined: Sep 29, 2000
Then you are stuck doing dumb stuff < Cindy wishing she could give a peice of her mind to the folks that drive tech design based on executive logic - grrrrrr >. I suppose you could use a case statement - but that is no better that the if statements . . . . it is just plain procedural.
Not knowing anything else about your objects, I'm wondering if the original (production code) objects are built properly.
If your testcase is "make sure all the objects start".. then you should be able to handle all the object by their base class, and call the 'startMeUp()' method on the base class reference, and no problems will ensue.
But if the objects name the method different things like 'startMeUp' and 'run()' and 'doIt()' Then I have sympathy for the tester and I shake my fist at the original coder.
Alternately, if your objects are designed properly, but you are performing different tests on the different objects, then this is just a fact of life.. you can't dynamically and polymorphically do this.
Instead of using instanceof, simply don't use a superclass but do hardcode each object's test cases. We have done something somewhat similar here at my job. There is a TestRunner class. There is also a abstract TestCase class. TestCase contains a run() method (among others). For every object we want to make a TestCase for, we make a new class, which provides the implementation for run() method. Inside this run method is where we'd put the object-specific method calls, etc. The TestRunner class contains an array of TestCase classes, which can then polymorphically call the run() method of each TestCase. So we don't use instanceof, so much as brute force.
That would seem (to me) to be only marginally more work than the 'framework' of sorts you have to construct using instanceof and a bunch of if-elses. I know that from my own experience, i've tried to do something simliarly 'clever' and just ended up wasting time.
Did any of that make sense? [This message has been edited by Mike Curwen (edited August 15, 2001).]
Joined: Feb 22, 2001
Mike, Yes, that does make sense and it is a better solution than all these ugly instanceof's. Coincidentaly I am actually already using TestCase and TestRunner classes. Basically what I'm writing is an automated regression tester that sits on top of the junit framework. The objects in question are servlet request objects that are serialized to .xml and submitted. One tool records the .xml that is submitted by QA folk and stores it (along with corresponding response objects). The regression tester re-builds the objects (which are basically instances of the command pattern), submits them and then verifies that the results match those originally obtained (and verified) by the QA folk. The problem arises because the request objects are only a weak implementation of the command pattern: they encapsulate data, but do not know how to submit themselves. So the equivelent of the startup() method you described doesn't even exist in the objects. This is done for performance reasons, there is a client class that does the work of setting up the service to submit once instead of having an object set up a service everytime it wants to submit itself. I'm pretty green and totally self-taught, but it seems to me that it would have been better to make the requests smarter and to give them a ServicePool to draw from. Would have been almost as fast and a hell of a lot cleaner. Anyway, I'm rambling. But you seemed interested so I thought I'd give you the background. I'll follow your suggestion and make wrapper objects for each request type that will know how to submit themselves and also do some type dependent logging work. ( won't call the wrappers TestCase though, my TestCase bundles up arrays of Requests and their associated Responses ). Thanks for the suggestion, Joe
[This message has been edited by Joe Von (edited August 17, 2001).]