[英]On a extended class, can i use a getter and setter of a class that implements multiple interfaces
我有一個帶有通用代碼的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(){
}
想法是通過以下方式使用代碼:
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>)
方法不適用於參數(ArrayList<Doctor>)
”。
有什么方法可以讓CurrentGroup類將Doctor列表作為ArrayList保留,並且仍在Analizer類的AnalizePeople方法上工作?
這一切都取決於接口的實際合同 。 您將其指定為
public interface Group{
List<Person> getPeople();
void setPeople(List<Person> people);
}
但是...是否可以保證方法getPeople
返回與先前setPeople
調用中傳遞的列表(引用)相同的列表(引用)? 並保證它是可變的嗎?
如果您對兩個問題的回答均為“真”,那么您將無法做您想做的事情。 在這種情況下,合同意味着您可以使用任意Group
和Person
實現來執行group.getPeople().add(person)
。 將其設置為僅接受Doctor
實例的List<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
但不保留對setPeople
調用者提供的List
實例的引用,那將完全不同。 然后,通用簽名可以像這樣放寬:
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
成為具有指定其成員類型的類型參數的泛型類,但是如果您必須處理已經存在的代碼,那可能是不可能的更改。
如果將醫生添加到由getPeople()
表示的列表中,則它將透明地工作,因為它實現了Person
。
順便說一句:您的方法應稱為analizePeople
以符合Java方法命名約定。
這不會工作:
public void AnalizePeople(Group group){
List<Person> items=group.getPeople();
因為Group沒有定義getPeople
。
這會令人困惑:
public class Group extends AbstractGroup(){
因為已經有一個名為Group
的接口。
“有沒有辦法讓分組班級保存一個Doctor列表,並且仍然使用Analizer類中的AnalizePeople方法?”
AnalizePeople(sic)在Analizer類中。 您的新班級Group當前與Analizer沒有關系,因此將無法調用AnalizePeople()。
請通過縮進至少4個空格來正確格式化代碼。 同樣,方法名稱應以小寫字母開頭。 並且“分析”應拼寫為“ y”而不是“ i”。
目前還不清楚您到底想實現什么目標,而目前正在問什么卻完全是胡言亂語。 請澄清。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.