如何使用子类或超类定义Java函数的返回类型和参数?

时间:2018-02-18 19:35:33

标签: java list generics inheritance arraylist

例如,如果我有像

这样的功能
public List<E> sort(ArrayList<E> list) {...}

我的同学告诉我,我们应该使用List作为返回类型,因为返回类型应该尽可能广泛。他的理由是,如果我们当前返回一个ArrayList,我们可以更改为返回LinkedList或其他类型。它增加了灵活性。

但我们收到的函数参数应该尽可能窄。这是因为我们可能需要在sort函数中使用一些只由ArrayList实现的函数。

所以我的问题是:是否有任何广泛接受的指南/最佳实践建议函数的形式参数应尽可能窄?如果不是,反对的主要论点是什么?

=============================================

只是澄清一下。

public List<E> sort(ArrayList<E> list) {...}

这只是一个例子,List和ArrayList可以被任何其他Super Class和SubClass替换。我们假设SubClass中只存在一些函数。

public <E> SuperClass<E> sort(SubClass<E> object) {...}

3 个答案:

答案 0 :(得分:2)

大多数程序员都会同意,尽可能广泛的回报是你所描述的好事(由于灵活性因素)。

我相信很多人会争辩说,尽可能广泛的指南也适用于参数,因为它允许您从更广泛的范围使用您的函数:如果在代码中的某个位置有LinkedList如果使用List类型的参数定义了该方法,那么该地方将能够调用您的方法(如果需要排序),但如果使用参数定义它,则无法调用您的方法类型为ArrayList

所以一般来说,尽可能广泛是一个很好的指导方针。当然,由您(作为方法的作者)决定“尽可能广泛”对您来说意味着什么。具体来说,如果你可以使它更广泛但有一些成本(例如,更复杂的实现),你必须决定是否愿意接受这种额外的复杂性(更高的错误机会)以换取更广泛的适用性。

答案 1 :(得分:1)

要正确应用泛型,您应该接受并返回由ArrayList,LinkedList等实现的相同接口。不要忘记返回类型参数<E>

public <E> List<E> sort(List<E> list) {
    ...
    return list;    
}

此方法适用于以下所有List实现(我不记得所有):

List<String> vector = new Vector<>();
List<String> stack = new Stack<>();
List<String> arrayList = new ArrayList<>();
List<String> linkedList = new LinkedList<>();

List<String> newList1 = new Main().sort(vector);
List<String> newList2 = new Main().sort(stack);
List<String> newList3 = new Main().sort(arrayList);
List<String> newList4 = new Main().sort(linkedList);

答案 2 :(得分:1)

你的同学应该告诉你从正确的声明开始:

List

因为如果你想在不传递Comparator的情况下对List进行排序,那么这些元素需要以某种方式,可比较

然后,一般,返回ArrayList vs List,选择应该是Set。但不总是。考虑SortedSet vs SortedSet一分钟,返回Set使调用者明白返回的Set实际已排序;而不是返回{{1}}。