改变java中子类方法的语义

发布于 2024-09-25 07:47:51 字数 616 浏览 1 评论 0原文

我最近学习了 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);
    }
}

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

坚持沉默 2024-10-02 07:47:51

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

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

这是否打破了继承的 is-a 理念?

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

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

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

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.

月朦胧 2024-10-02 07:47:51

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

就我个人而言,我建议学习如何使用 Google guava-libraries 不可变的排序数据结构“功能”,要获得回顾概述,请浏览 youtube。

但在这里,我在标准 Java 中做了示例,说明如何使用 TreeSet 自动排序 - 自定义类、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]]

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]]
橘寄 2024-10-02 07:47:51

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

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文