我有一个包含公共代码的Java包,它将在团队中分发以处理两个项目。
一个项目已在进行中,因此我将不得不调整现有代码以使用这个新软件包。
该包具有类似于以下内容的接口和类:
public interface Person{
}
public interface Group{
List<Person> getPeople();
void setPeople(List<Person> people);
}
public abstract AbstractPerson implements Person{
}
public abstract AbstractGroup implements Group{
List<Person> people;
public List<Person> getPeople(){
return this.items;
};
public void setPeople(List<Person> people){
this.people=people;
}
}
public class Analyzer(){
public void analyzePeople(Group group){
List<Person> items=group.getPeople();
....
}
}
一个已在进行中的项目我们有一个类将会像这样改变:
public class Doctor extends ExistingClass implements ExistingInterface,Person {
}
我没有小组课,所以我要实现它,
public class CurrentGroup extends AbstractGroup(){
}
ideia是以下列方式使用代码:
CurrentGroup currentGroup=new CurrentGroup();
currentGroup.setPeople(new ArrayList<Doctor>());
...
Analyzer analyzer=new Analyzer();
analyzer.analyzePeople(currentGroup);
我有两个问题:
所有这一切都应该工作,因为ArrayList实现了List和Doctor实现了Person,但它没有,因为eclipse显示错误“Processo类型中的方法setPeople(List<Person>)
不适用于参数{{1} }”。
有没有办法让CurrentGroup类将Doctor列表保存为ArrayList,仍然可以使用Analizer类中的方法AnalizePeople?
答案 0 :(得分:3)
这完全取决于界面的实际合同。您将其指定为
public interface Group{
List<Person> getPeople();
void setPeople(List<Person> people);
}
但是...是否保证方法getPeople
返回在先前setPeople
调用中传递的相同列表(引用)?是否保证可变?
如果你用true回答这两个问题,那么就没有办法做你想做的事。在这种情况下,合同意味着您可以使用任意group.getPeople().add(person)
和Group
实施Person
。将其设置为只接受List<Doctor>
个实例的Doctor
会违反该合同。
如果列表不需要是可变的,你可以这样做:
List<Doctor> list=…;
group.setPeople(Collections.unmodifiableList(list));
在Java 8之前,你必须使用
group.setPeople(Collections.<Person>unmodifiableList(list));
这样可行,因为List<Doctor>
在检查时保证返回Person
个实例,但是您无法添加任意Person
个实例,因为此类修改尝试在运行时被拒绝。
但这意味着,为了添加Doctor
个实例,您必须在某处保留对原始List<Doctor>
的引用。
如果Group
应该保留Person
但不保留对List
调用者提供的setPeople
实例的引用,那将完全不同。然后,通用签名可以像这样放松:
interface Group {
List<Person> getPeople();
void setPeople(List<? extends Person> people);
}
class AbstractGroup implements Group {
final ArrayList<Person> people=new ArrayList<>();
public List<Person> getPeople() {
return people; // or Collections.unmodifiableList(people)
}
public void setPeople(List<? extends Person> people) {
this.people.clear();
this.people.addAll(people);
}
}
然后,你可以简单地说
List<Doctor> list=…;
group.setPeople(list);
将小组的人员初始化为您的医生,但是,您没有保证它是一个同质的医生组(除非它是一个纯粹的本地对象,您不会分发给可以修改它的代码)
还可以选择使Group
具有指定其成员类型的类型参数的泛型类,但如果必须处理已存在的代码,则可能会发生不可能的更改。
答案 1 :(得分:0)
如果您将医生添加到getPeople()
所代表的列表中,那么它将透明地工作,因为它实现了Person
。
BTW:您的方法应该被称为analizePeople
以保持Java方法命名约定。
答案 2 :(得分:0)
这不会&#39;工作:
public void AnalizePeople(Group group){
List<Person> items=group.getPeople();
因为小组没有定义getPeople
。
这会令人困惑:
public class Group extends AbstractGroup(){
因为已经有一个名为Group
的接口。
&#34;有没有办法让小组课程拿着医生名单,仍然可以使用Analizer班的方法AnalizePeople?&#34;
AnalizePeople(sic)属于Analizer类。您的新班级组目前与Analizer无关,因此无法调用AnalizePeople()。
请通过缩进至少4个空格来正确格式化您的代码。此外,方法名称应以小写字符开头。并且&#39;分析&#39;应拼写为&#39; y&#39;不是&#39; i&#39;。
目前还不完全清楚你要达到的目标是什么,你现在要问的是完全的胡言乱语。请澄清。