Cześć. Buduję sobie klasę Menu, która zawiera guziki. Guziki mogą być abstrakcyjne, czyli nie odpowiadające żadnemu obiektowi i realne czyli odpowiadające jakiemuś obiektowi. Robie tak dlatego że chcę żeby moje menu było ogólne i żeby dało się go użyć nie tylko z jednym typem struktury danych.
Mój problem polega na tym że trochę zaplątałem się w implementacji. Nie mam za dużego doświadczenia z interfejsami. Oto mój kod>
Menu:
package model;
import java.util.ArrayList;
import java.util.List;
public class Menu {
private List<Button> buttons = new ArrayList<Button>();
private int numberOfButtons = 0;
private int currentButton;
private int topButton;
private int maxButtonsPage;
private Button parent;
private List<NamedObject> objects = null;
//real menu with all real buttons
public Menu(List<NamedObject> objects, int maxButtons, Button parent){
this.numberOfButtons = objects.size();
this.currentButton = 0;
this.topButton = 0;
this.maxButtonsPage = maxButtons;
this.parent = parent;
this.objects = objects;
for(int i = 0; i < objects.size();i++){
buttons.add(new Button(objects.get(i),this));
}
}
public Menu(Button parent){
this.numberOfButtons = 0;
this.currentButton = -1;
this.parent = parent;
this.topButton = -1;
buttons = null;
}
//abstract menu with all abstract buttons
public Menu(List<String> names, List<Behavior> behaviors, Button parent){
this.numberOfButtons = names.size();
this.currentButton = 0;
this.topButton = 0;
this.parent = parent;
for(int i = 0; i < names.size();i++){
buttons.add(new Button(names.get(i), behaviors.get(i), this));
}
}
public Button getParent(){
return this.parent;
}
public void addRealButton(NamedObject object){
if(this.buttons == null){
this.currentButton = 0;
this.topButton = 0;
}
this.buttons.add(new Button(object, this));
}
public void addAbstractButton(String name, Behavior behavior){
if(this.buttons == null){
this.currentButton = 0;
this.topButton = 0;
}
this.buttons.add(new Button(name, behavior, this));
}
public int getCurButton(){
return this.currentButton;
}
public void setCurButton(int button){
this.currentButton = button;
}
public Button getButton(int button){
return buttons.get(button);
}
public int getNoButtons(){
return this.numberOfButtons;
}
public List<Button> getButtons(){
return this.buttons;
}
public void setButtons(List<Button> buttons){
this.buttons = buttons;
this.numberOfButtons = buttons.size();
}
public int getTopButton(){
return this.topButton;
}
public void setTopButton(int number){
this.topButton = number;
}
public void setSubMenu(int button, Menu menu){
this.buttons.get(button).setSubMenu(menu);
}
public Menu getSubMenu(int button){
updateMenu();
return this.buttons.get(button).getSubMenu();
}
public void advanceCurButton(){
if (this.topButton + maxButtonsPage - 1== this.currentButton && this.currentButton < this.numberOfButtons - 1)
++this.topButton;
if (this.currentButton != this.numberOfButtons-1)
++this.currentButton;
}
public void retardCurButton(){
if (this.currentButton == this.topButton && this.currentButton != 0)
--this.topButton;
if (this.currentButton != 0)
--this.currentButton;
}
public Menu getSelSubMenu(){
return this.buttons.get(this.currentButton).getSubMenu();
}
public Button getSelButton(){
return this.buttons.get(this.currentButton);
}
private void updateMenu(){
buttons = null;
for(int i = 0; i < objects.size();i++){
buttons.add(new Button(objects.get(i),this));
}
}
}
Jak zapewne widać w kodzie, jest tam Interface Behavior. Jets on po to żeby program wiedział co robić kiedy kliknąć na abstrakcyjny guzik. W wypadku realnego guzika chcę tylko wejść w podmenu guzika, lub nic nie robić jeśli takowego nie ma.
package model;
import java.util.List;
public class Button {
private Menu submenu = null;
private String name = "";
private boolean hasSubMenu;
private boolean hasCustomBehavior = false;
private NamedObject object = null;
private Menu parent;
private Behavior behavior;
//2 real button constructors
public Button(NamedObject object, Menu menu, Menu parent){
this.submenu = menu;
this.hasSubMenu = true;
this.parent = parent;
this.name = object.getName();
this.object = object;
}
public Button(NamedObject object, Menu parent){
this.hasSubMenu = false;
this.parent = parent;
this.name = object.getName();
this.object = object;
}
//one abstract button constructors
public Button(String name, Behavior behavior, Menu parent){
this.hasCustomBehavior = true;
this.name = name;
this.behavior = behavior;
}
public Menu getParent(){
return this.parent;
}
public void setName(String newName){
this.name = newName;
}
public String getName(){
return this.name;
}
public Menu getSubMenu(){
return this.submenu;
}
public void setSubMenu(Menu submenu){
this.submenu = submenu;
this.hasSubMenu = true;
}
public boolean hasSubMenu(){
return this.hasSubMenu;
}
public boolean hasCustomBehavior() {
return this.hasCustomBehavior;
}
public void setCustomBehavior(Behavior behavior) {
this.hasCustomBehavior = true;
this.behavior = behavior;
}
public Behavior getBehavior(){
return this.behavior;
}
public Object getObject(){
return this.object;
}
//tutaj mam problemy
public void setRecursiveObjectMenu(RecursiveNamedObject obj){
for (int i = 0; i < obj.getNumberOfChildren(); i++){
this.submenu = new Menu(obj.getChildren(), 6, this);
setRecursiveObjectMenu((RecursiveNamedObject) obj.getChild(i));
}
}
}
W ostatniej metodzie próbuję stworzyć całe menu(wliczając pod menu i pod pod menu itd.). RecursiveNamedObject to interfejs>
package model;
import java.util.List;
public interface RecursiveNamedObject {
public Object getChild(int index);
public int getNumberOfChildren();
public String getName();
public List<Object> getChildren();
}
Mój problem polega na tym że jak mam interfejs który ma metodę na przykład getChildren która ma zwracać listę obiektów, to nie moge z góry zakładać jakiego typu będzie ta lista, czy List<Directory>, czy List<Cubes>, dlatego wpisałem List<Object>. Ale teraz w klasach które implementują ten interfejs, chciałbym metodą getChildren zwracać rózne typy list, na przykład List<Directory>, czyego niestety zrobić nie mogę.
Mam jeszcze kilka problemów, ale nie umiem ich wytłumaczyć, myślę że będziecie wiedzieć o co chodzi jak zobaczycie kod.