This discussion builds on another topic whether to use interface or abstract class. I think it was a good dialogue and the responses were fantastic, Thank You! Really, I could have continued that thread, but this touches off on a different issue and I think it merits its own thread. Maybe, this time, I can get one of the informal authors to pitch in his brilliance . Along the way, I have some doubts whether I am using the correct OO jargon; please correct me if I am wrong. I hate to rub with someone on semantics . I have an abstract class DataReader and there are two subclasses (or Concrete classes or concrete subclasses ) LegacyReader and NewOutputReader. The end result of both Reader(s) are the same. They both read data from an underlying stream which comes from a text file. This file has a logical structure which characterize transactions where within each transaction there are individual segments representing specific details about the transaction. The goal of these Reader(s) is to create and fill an array of SegmentUnit. This array as a whole makes up one transaction. For clarity, let me just briefly outline what happens next. Once an array of SegmentUnit is filled, it is serialized to a Socket and another Java (server) process that creates a local connection to a database. Upon deserialization, (and following my little protocol) appropriate actions will be performed in the database. The SegmentUnit Object encapsulates the fields, which represent a given table, such as an insertStatement, DeleteStament, and numBindVariables etc. These are all populated by a reader by calling any of the setters on a given SegmentUnit. My question is regarding the deleteKeyValue field, which is of type String and represents a value to be filled in (as a parameter) to a given deleteStatement. The NewOutputReader allows multiple keys for a deleteStatement. Now I need to modify the application allowing for this requirement. Fortunately, this is pretty easy all I need to do is the following:
Modify SegmentUnit and make deleteKeyValue a String array.
The NewOutputReader should pass in an array to the setDeleteKeyValue().
Need to review, how the LegacyReader will call set. The entire purpose of these post
Modify the server objects to handle the deleteKeyValue as an array.
Let�s review (in mixed order) how to solve each one. The server part is really easy, just change this: to the following:
The NewOutputReader is still in the coding stage, and the implementation is simple. Just parse out the multiple keys from the underlying stream and pass an array of values to the LegacyReader. Modifying the internals of SegmentUnit is also a no-brainer, simply change the deleteKeyValue from a String to String array, and have getDeleteKeyValue return a String rather then String. BTW, I don�t think function overloading will work here as the only difference will be the return type, please confirm. What we are left with the Need to review, how the LegacyReader will call set, which is the subject of this topic and the question is with the setDeleteKeyValue(). I am thinking of two ways how to do this either we can modify the LegacyReader to have it pass a String, and simply modify the setDeleteKeyValue() to take a string array. The source for LegacyReader is available for modification. However, it appears the with an OO language this can be avoided. Another way is with some arm twisting and the instanceof operator:
I modified the parameter from String to Object and with the help of the instanceof operator we have somewhat achieved OO polymorphism. The LegacyReader does not need modification it still passes just a String, and the NewOutputReader simply passes an array, and the setDeleteKeyValue() handles them nicely. Nevertheless, I call this the arm-twisting way. Something just seems wrong and unorthodox with the use of instanceof. What are your thoughts, I would like to hear them. I have put in quite some time in this post and sort-of a thinking loud session. Maybe this can help someone who knows. BTW, I guess a sheriff would address this, now this is the longest post that I put in. Is there a problem with these long posts? Should I refrain from them? Should I stop apologizing for these long posts? Are they at all helpful? I had to split up the post; it continues with the next post ... [ June 19, 2003: Message edited by: Leslie Chaim ]
Normal is in the eye of the beholder
Joined: May 22, 2002
Continued from above� Now, I was all ready to post this but � I am not done yet . I was sitting on this for quite some time and I just want to share this simple idea: sometimes it�s useful to write down your problem and read it a few times. It worked very nicely for me! It just occurred to me that the real solution is to simple use function overloading . Simply add a method setDeleteKeyValue() which takes a String, this will be used by the NewOutputReader. Then just modify the setDeleteKeyValue which takes a String:
I guess after all of this maybe the subject should have been code refactoring. Nevertheless, now I am done, thanks for reading (and for your comments) . Leslie [ June 19, 2003: Message edited by: Leslie Chaim ]
I hate to rub with someone on semantics I can't imagine who this might be directed at. I have an abstract class DataReader and there are two subclasses (or Concrete classes or concrete subclasses ) Concrete subclasses is probably best. Concrete and subclass are two different things (though you usually don't bother talking about whether a class is concrete unless it's a subclass of an abstract class). No need for capitalization here. System.err.println ("Gee, this should never happen, but I guess it did!"); Naah, too passive. Why would this possibly happen? Only if the method is called with the wrong argument type - neither a String nor a String. So make it the caller's fault. Throw a ClassCastException (or maybe IllegalArgumentException) that says hey, someone else screwed up here, not me. Of course your method API should also document that it expects a String or String in this case... I guess this is moot since as you've subsequently discovered it's generally better to have two methods, one for String and one for String, rather than once for Object which waits until run time to find out whether the parameter it's passed is of the correct type. I might go one step further and change the names slightly, since overloaded methods are effectively like different methods as far as the compiler's concerned - and the name setDeleteKeyValue doesn't quite sound right if there's more than one value. I'd go with setDeleteKeyValue(String) setDeleteKeyValues(String) This also can address a lingering question on the get methods: Modifying the internals of SegmentUnit is also a no-brainer, simply change the deleteKeyValue from a String to String array, and have getDeleteKeyValue return a String rather then String. BTW, I don�t think function overloading will work here as the only difference will be the return type, please confirm. Correct, if you have two methods which differ only in return type, it's not overloading - it's just plain illegal. But you could have two methods with different names: public String getDeleteKeyValue(); public String getDeleteKeyValues(); This is a bit risky though - what should you do if multiple delete keys have been set, and someone calls the singular getDeleteKeyValue()? It's probably an error. It might be safer to only offer getDeleteKeyValues(), and force prorammers to just iterate through however many values there are. If the caller is certain there should be exactly one, that might be a good place for an assertion:
sometimes it�s useful to write down your problem and read it a few times. Yup. You may also enjoy a few wiki links: CardBoardProgrammer, CardboardAnalyst, and RubberDucking. Pets and other innocent bystanders work well for this too. [ June 19, 2003: Message edited by: Jim Yingst ]
"I'm not back." - Bill Harding, Twister
Joined: May 22, 2002
Thanks Jim for you invaluable input. It is really calm and collective.
subject: OO question: Polymorphism with instanceof