代码之家  ›  专栏  ›  技术社区  ›  Falmarri

java中子类方法的语义变化

  •  1
  • Falmarri  · 技术社区  · 14 年前

    我最近学了3种新语言,我开始把它们搞混了。几年来,我还没有用Java做任何特别复杂的事情(Android之外)。如果可能的话,我很难记住:

    我主要是对arraylist进行子类化,以便保持arraylist的有序性。我正在尝试覆盖 add(object) 方法,但我希望它返回一个int而不是布尔值(添加的对象的位置)。但我的方法的返回类型有错误。

    我想要的语言是可能的吗?子类中的方法是否可以返回与超类方法不同的内容?

    还是我想做些傻事?这是不是破坏了 is-a 继承的概念?我应该封装一个数组列表而不是扩展它吗?

    作为参考,我想做的一部分:

    
    public class AuthorArray extends ArrayList \{
    
        @Override
        public int add(Author object) {
            super.add(object);
    
            Collections.sort(this, new SortByLastName());
    
            return this.indexOf(object);
        }
    }
    
    3 回复  |  直到 14 年前
        1
  •  3
  •   Péter Török    14 年前

    子类中的方法是否可以返回与超类方法不同的内容?

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

    这是否打破了继承的概念?

    是的 . 的用户 ArrayList 希望得到一个 boolean 返回值来自 add ,并按照添加元素的相同顺序查看元素,您将打破这种期望。别那么做。

    我应该封装一个数组列表而不是扩展它吗?

    对。然后,您可以用您喜欢的任何契约定义自己的接口。但首先, 考虑使用 TreeSet 相反 .

        2
  •  1
  •   Margus    14 年前

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

    我个人建议学习如何使用 Google guava-libraries 使用“函数”对数据结构进行不可变排序,要获得刷新概述,请浏览YouTube。

    但在标准Java中,我举例说明了如何使用TeSEET AutoStRe-自定义类、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]]
    
        3
  •  0
  •   Christopher Hunt    14 年前

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

    如果上面的顺序不是您想要的,那么您有两个选择——要么使用collection.sort()方法对列表排序,要么使用sortedset。这两种方法都可以采用比较器。

    我从来没有发现扩展Java集合框架的必要性,也不建议在这种情况下这样做。