• Post Reply Bookmark Topic Watch Topic
  • New Topic

Thinking problem: on extending Collection classes.  RSS feed

 
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

im a beginner of Programming. Couple hours I began an idea of creating a modified List based on ArrayList, it would do pretty much same thing as ArrayList but with one exception: the List doesnt accept redundant data e.g. functions as if it was a Set. So I wrote the line:



and then I become stuck.. On everything. I do not know how to proceed. At first, the basic ideas I have in mind was


  • I need to create a method add(String s)
  • so that It add elements in the list but does nothing if the list already contains the said element.
    so I drafted a method like this


    at this moment I was stuck at how to think this through.
    Firstly I cant explain my own code: what's this.add(s), it cant be the same function as it calls from, so what is it, from ArrayList.add()?

    secondly I want to create a addAll(Collection<String> c) too so that when I call it, it will convert a whole , say, ArrayList to MySetList. but the questions is, I dont know what variable to use for this addAll method. My idea would be something like this:


    I began to realize I lost track on this(and I know this maybe the problem in basic thinking pattern of OOP but despite quite some OOP lectures I cant wrap my mind around this). Can somebody tell me what I done wrong and if you were the one having a similar drafting process, what would you do first . how would you put things straight etc..

    help would be greatly appreciated.
     
    Ranch Hand
    Posts: 479
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I think you almost have it.

    Instead of this.add(s), however, what you want is super.add(s). super.add() will call the superclass' add method, which is what I think you want here. this.add() will, in fact, call the add method that you are writing, recursively, and that doesn't seem to be what you intend.

    Your addAll should also call super.add() each time it finds an element that it has judged should be added.

    In terms of OO, you are extending the ArrayList class to keep duplicates out of the list. I think this is a proper use of OO inheritance, though maybe not for ArrayList -- more on that in a minute.

    Now, you also are not done. If you are creating such a class, you need to make sure that no caller can put anything in the list that is a duplicate, and there are two other methods to override -- add(int index, String s) and set(int index, String s) -- you need to implement both of those, check for duplicates, and do whatever you want with what they find. Otherwise you would have a class that sort-of checked for duplicates. (These are the two methods I found that would allow members in the list without your checking; any time you extend a class like this, you should inspect its method list to make sure you aren't leaving something out.)

    Now -- java already has a Set interface, and implementations of it, that will likely serve the general purpose better than what you would come up with without a lot of effort. But as an exercise in inheritance, or some special requirement that pushes you to use ArrayList in this fashion, this is fine.

    rc
     
    sean neo
    Greenhorn
    Posts: 2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thank you rc!

    your reply helps me a whole lot. The reason I need ArrayList is I really need to keep tracking of the index of those elements I put it there.

    After reading this, I continued on the drafting. And I have more questions this time:s

    I would like to create a C-tor which converts the whole given ArrayList to MySetList (using addAll). Something like this:


    But I dont know how to write the C-tor code. I tried something like this but feels bad about it:

    I would like to know how would you write the C-tor.

    As you can see I am very fresh in programming, I have a feeling that to answer to most of my questions, you would have to explain some of the very basic stuff for me to understand my own question. So I would like to thank you in advance for your patience.
     
    Marshal
    Posts: 56610
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Ralph Cook wrote: . . . Now -- java already has a Set interface, and implementations of it, . . .
    Agree with Ralph Cook. If you go through the Java™ tutorials section, you will find a Set implementation which records the order of insertion. That might be more appropriate for your requirements.

    When you are doing inheritance, you should check the description of what you are inheriting from, so I looked at ArrayList and it says it implements List<E>. When you look at List, you read
    . . . lists typically allow duplicate elements.
    . . . and a few lines later
    It is not inconceivable that someone might wish to implement a list that prohibits duplicates, by throwing runtime exceptions when the user attempts to insert them, but we expect this usage to be rare.
    So your design of class is specifically permitted in the API documentation, where there is a suggestion about how to implement it.

    But I still think a Set might be much easier for you to use.
     
    Ralph Cook
    Ranch Hand
    Posts: 479
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    If by C-tor you mean a constructor, then yes, that is exactly how I would write it



    There is no need, though no harm, in saying "this.addAll()"; they will do the same thing.

    Now, something else you said is a little disturbing: "I need to keep tracking of the index of those elements..." Keep in mind that, if you extend ArrayList, then the user can remove elements from the list. If he does, the indices of all the other elements will change; if you have stored that index, then what you stored will NOT have changed, and will be incorrect.

    You could also override the remove() method and make it non-functional, but that doesn't solve the whole problem. A user could also use set() to put a different object in the list at a given index. I suppose you could disable that as well...
     
    Campbell Ritchie
    Marshal
    Posts: 56610
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    There is a rule of thumb: "favour composition over inheritance."

    It might be easier for you to create a class which does not extend anything, but has a List as a field. I can imagine it looking like thisThis architecture is called a wrapper class.
     
    Ralph Cook
    Ranch Hand
    Posts: 479
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:There is a rule of thumb: "favour composition over inheritance."

    It might be easier for you to create a class which does not extend anything, but has a List as a field. I can imagine it looking like this


    This architecture is called a wrapper class.


    Well, it's a good example of why I'm suspicious of this supposed rule.

    You are calling for the writer to re-implement "about 20 other methods". In what way is that easier? The whole point of inheritance, of OO in general, is to re-use what others have already written and debugged.

    Now, there are cases where you COULD use inheritance that I don't think ARE appropriate; I am NOT saying you should always use it. It is a "kitchen match" tool (you can only use it once), for one thing, and for another not all classes that can be extended should be extended the way they are. The best example of this I've ever seen in the java.util.Stack class which, for reasons passing understanding, extends Vector. I think this is a horrible use of inheritance; there are methods in Vector that have no business in a Stack class.

    So, I don't think this is a good idea, and I don't think it should be called a "Wrapper" class. I think it should be called "let's reimplement ListArray, without duplicates".

    rc
     
    Campbell Ritchie
    Marshal
    Posts: 56610
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Ralph Cook wrote: . . . Now, something else you said is a little disturbing: "I need to keep tracking of the index of those elements..." . . .
    Agree that is disturbing.

    I think you need to go back to a sheet of paper, a pencil and an eraser. Preferably a large eraser. As I keep telling our undergraduates. I have next to me an eraser which looks as if it would do serious harm to a student if I threw it at him

    I suggest you draw what the structure of this collection ought to be. If you add "Campbell" "Ralph" "Sean", what will it look like? How are you going to record those indices? What will it look like if you add those three again? What will it look like if you remove one element? How are you recording indices?

    Look at the List interface and the Set interface. Look at the Map interface. Can you have a Map of numbers to elements? You might call that a Map<Integer, Foo>. Find out what the underlying data structure for an ArrayList is. The name is a hint, so you might guess correctly. If it's an array, remember that arrays directly link index to element. See whether you can think of any other solutions. The more possibilities you consider, the better your final solution will be. Even if some possibilities turn out after 5 minutes' consideration to be nonsense!
    Write down your requirements carefully, and decide whether extending an existing class, or creating a wrapper, or using a Set implementation will best serve your purposes. I think an hour with pencil and paper now will save you many hours programming later.

    We like to reserve "Beginning Java™" for easy questions, and this isn't easy, so I am moving it.
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!