views:

46

answers:

3

I've recently learned like 3 new languages and I'm starting to get them confused. I haven't worked Java in doing anything particularly complex (outside of android) in a couple years. I'm having trouble remembering if this is possible:

I'm subclassing ArrayList mainly so I can keep the arraylist ordered. I'm trying to override the add(object) method but I want it to return an int instead of a boolean (the location of the object that was added). But I'm getting errors on the return type of my method.

Is what I want even possible in the language? Can you have a method in a subclass return something different than the superclass' method?

Or am I trying to do something stupid? Is this breaking the is-a idea of inheritance? Should I just encapsulation an arraylist instead of extending it?

For reference, a portion of what I'm trying to do:


public class AuthorArray extends ArrayList \{

    @Override
    public int add(Author object) {
        super.add(object);

        Collections.sort(this, new SortByLastName());

        return this.indexOf(object);
    }
}
+3  A: 

Can you have a method in a subclass return something different than the superclass' method?

In general, no. The only exception is covariant return types, when an overridden method returns a subclass of the return type in the base class/interface method. This became possible with Java5, and is good practice. But your case does not fall into this category.

Is this breaking the is-a idea of inheritance?

Yes. Users of ArrayList expect to get a boolean return value from add, and see the elements in the same order they added them, and you would break that expectation. Don't do that.

Should I just encapsulation an arraylist instead of extending it?

Yes. Then you can define your own interface, with whatever contract you prefer. But first, consider using a TreeSet instead.

Péter Török
Ah thank you. I could not for the life of me find a sorted collections class for some reason. I dunno what my problem was
Falmarri
A: 

The List interface guarantees that elements will be returned in the same order that they are added. Thus if you only have one thread manipulating the list you can easily perform an add and then request its size. size - 1 is the ordinal value of the element.

If the above order is not what you want then you have two choices - either sort the list using Collection.sort() methods, or use a SortedSet. Both methods can take on a comparator.

I've never found the need to extend the Java collections framework and do not recommend that you do so in this circumstance.

Christopher Hunt
+1  A: 

Changing semantics is bad. In your case, changing method name from add to myadd would fix your problem, if you want a simple fix.

Personally i would recommend learning how to use Google guava-libraries immutable, sorted data structures with 'function', to get a refresher overview, browse youtube.

But here in standard Java, I made example, how to use TreeSet autosort - custom class, 2 value comparator, and efficient binary search equivalent.

public static class customC {
    private String name; 
    private int value;

    public customC(String name, int value) {super();this.name = name;this.value = value;}
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public int getValue() {return value;}
    public void setValue(int value) {this.value = value;}

    @Override
    public String toString() {
        return new StringBuilder().append("[").append(this.name)
                .append(":").append(this.value).append("]").toString();
    }
}

public static void main(String[] args) {
    TreeSet<customC> ts = new TreeSet<customC>(new Comparator<customC>(){
        public int compare(customC a, customC b) {
            int result = a.getName().compareToIgnoreCase(b.getName());
            return (result != 0 ? result : a.getValue() - b.getValue());
        }
    });
    ts.add(new customC("ab", 1988));
    ts.add(new customC("ab", 1979));
    ts.add(new customC("ba", 1988));
    ts.add(new customC("ab", 1984));
    ts.add(new customC("ab", 1980));
    customC ce = new customC("ab", 1983);
    ts.add(ce);

    StringBuilder sb = new StringBuilder();
    sb.append(ts.headSet(ce).last()).append(" comes before ")
        .append(ce).append("\n").append(ts);

    System.out.println(sb.toString());
}

This will output:

[ab:1980] comes before [ab:1983]
[[ab:1979], [ab:1980], [ab:1983], [ab:1984], [ab:1988], [ba:1988]]
Margus