在java中更改子类方法的语义

时间:2010-09-26 22:29:23

标签: java inheritance sorting override overloading

我最近学会了3种新语言,我开始让他们感到困惑。几年后我没有在Java上做任何特别复杂的事情(在android之外)。我无法记住这是否可能:

我主要是继承ArrayList,所以我可以保持arraylist的顺序。我试图覆盖add(object)方法,但我希望它返回一个int而不是一个布尔值(添加的对象的位置)。但是我的方法返回类型出错了。

我想要的语言甚至可能吗?你能在子类中有一个方法返回与超类'方法不同的东西吗?

还是我想做一些蠢事?这是否打破了is-a继承的想法?我应该封装一个arraylist而不是扩展它吗?

供参考,我正在尝试做的一部分:


public class AuthorArray extends ArrayList \{

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

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

        return this.indexOf(object);
    }
}

3 个答案:

答案 0 :(得分:3)

  

你能否在子类中有一个方法返回与超类'方法不同的东西?

一般来说,没有。当重写方法在基类/接口方法中返回返回类型的子类时,唯一的例外是协变返回类型。这在Java5中成为可能,并且是很好的做法。但是你的情况不属于这一类。

  

这是否打破了继承的想法?

即可。 ArrayList的用户希望从boolean获得add返回值,并按照他们添加的相同顺序查看元素,您就会打破这种期望。不要那样做。

  

我应该封装一个arraylist而不是扩展它吗?

是。然后,您可以使用您喜欢的任何合约定义自己的界面。但首先,考虑使用TreeSet代替

答案 1 :(得分:1)

改变语义是不好的。在您的情况下,如果您想要一个简单的修复,将方法名称从add更改为myadd可以解决您的问题。

就我个人而言,我建议学习如何使用Google guava-libraries不可变的排序数据结构和'function',以获得进修概述,浏览youtube。

但是在标准的Java中,我做了一个示例,如何使用TreeSet autosort - 自定义类,2值比较器和高效的二进制搜索等效。

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());
}

这将输出:

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

答案 2 :(得分:0)

List接口保证元素的返回顺序与添加元素的顺序相同。因此,如果您只有一个线程操作列表,则可以轻松执行添加,然后请求其大小。 size - 1是元素的序数值。

如果上述顺序不是您想要的,那么您有两个选择 - 使用Collection.sort()方法对列表进行排序,或使用SortedSet。这两种方法都可以采用比较器。

我从未发现需要扩展Java集合框架,并且不建议您在这种情况下这样做。