有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java中改变子类方法的继承语义

我最近学了三门新语言,我开始把它们弄糊涂了。我已经有几年没有用Java做过任何特别复杂的事情了(除了安卓)。我记不清这是否可能:

我正在对ArrayList进行子类化,主要是为了让ArrayList保持有序。我试图重写add(object)方法,但我希望它返回一个int而不是布尔值(添加的对象的位置)。但是我的方法的返回类型出现了错误

我想要的在语言中是可能的吗?子类中的方法能否返回与超类的方法不同的结果

还是我想做些蠢事?这是否打破了继承的观念?我应该封装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) 个答案

  1. # 1 楼答案

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

    就我个人而言,我建议学习如何使用Google guava-libraries不可变的、带有“函数”的排序数据结构,以便获得更新的概述,浏览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. # 2 楼答案

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

    如果上面的顺序不是你想要的,那么你有两个选择——要么使用集合对列表进行排序。sort()方法,或使用SortedSet。这两种方法都可以使用比较器

    我从未发现有必要扩展Java集合框架,也不建议您在这种情况下这样做

  3. # 3 楼答案

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

    通常不会。唯一的例外是协变返回类型,当被重写的方法在基类/接口方法中返回返回类型的子类时。这在Java5中成为可能,这是一个很好的实践。但你的案子不属于这一类

    Is this breaking the is-a idea of inheritance?

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

    Should I just encapsulation an arraylist instead of extending it?

    对。然后你可以用你喜欢的任何合同定义你自己的接口。但是首先,考虑使用^{}代替