java 实现协方差_Java集合协方差问题

Lets say we have a program which contains such classes:

public interface AbstractItem {

}

public SharpItem implements AbstractItem {

}

public BluntItem implements AbstractItem {

}

public interface AbstractToolbox {

//well the problem starts here...

public List getItems();

}

public ExpensiveToolbox implements AbstractToolbox {

private List items = new ArrayList();

public List getItems() { return this.items; }

}

public CheapTooblox implements AbstractToolbox {

private List items = new ArrayList();

public List getItems() { return this.items; }

}

Easy, right? Well lets say we now want to make a method like this (in some random class):

public void doImportantStuff(AbstractToolbox toolbox) {

//important stuff!

//this obviously won't work

List items = toolbox.getItems();

//do some stuffwith all items

}

Now the problem is that in Java collections with generics aren't covariant (hope that's the term I'm looking for) and I can't assign an ArrayList to a List. The only solution I can see here is to duplicate the code and do a version for each type, but that would obviously suck (what if we had more classes implementing AbstractToolbox with different lists?). Oh obviously the second solution would be to drop the generics and make a normal List, but is it a good practice?

Are there any design pattern/practices to tackle such problems?

@Edit: ok so I might not be precise enough. I want all the classes which extend AbstractToolbox to have a List of certain classes which extend AbstractItem and then I want a method that will take an AbstractToolbox as a parameter and do something on the items in its list (using the classes that would be defined in AbstractItem so all the items of every possible list would actually have them).

解决方案

You're probably going to need to take a look at using wildcard types for generics. Here's a quick link: What is PECS (Producer Extends Consumer Super)?

Quick answer: change the type to List extends AbstractItem>

Why can't you just assign this?

Imagine the code here...

List foo = new ArrayList();

foo.add(new BluntItem());

The static typing says this should work... but you can't do that! It would violate the ArrayList's type. That's why this is disallowed. If you change it to

List extends AbstractItem> foo = new ArrayList();

you can then do the assignment, but never add anything to the list. You can still retrieve elements from the list, however, as AbstractItems.

Is just using List (bare type) a good solution?

No, definitely not :-p

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值