在扩展类上,我可以使用实现多个接口的类的getter和setter

时间:2015-11-04 09:55:24

标签: java oop

我有一个包含公共代码的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);

我有两个问题:

  • 此类实现必须包含Doctor;
  • 的集合
  • 我当前代码的集合是ArrayLists;

所有这一切都应该工作,因为ArrayList实现了List和Doctor实现了Person,但它没有,因为eclipse显示错误“Processo类型中的方法setPeople(List<Person>)不适用于参数{{1} }”。

有没有办法让CurrentGroup类将Doctor列表保存为ArrayList,仍然可以使用Analizer类中的方法AnalizePeople?

3 个答案:

答案 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;。

目前还不完全清楚你要达到的目标是什么,你现在要问的是完全的胡言乱语。请澄清。