Interfejs i rzutowanie albo inny pomysł

0

Hej.
Mam taki problem mianowicie potrzebuje pewnego mechanizmy do napisani mojego programu.
Napiszę co na razie zrobiłem.
Mam mianowicie takie klasy:

 
public interface InputPattern {       
    public ArrayList<Double> getVector();  
}

public class InputPatternICPR1 implements InputPattern{

    private ArrayList<Double> vector = new ArrayList<Double>();
    private ArrayList<String> attributes = new ArrayList<String>();
    private String fileName = null;
    private String directory = null;

    public InputPatternICPR1(String path){
                
        File file = new File(path);     
        //adding filename to input pattern
        this.fileName = file.getName();
        //in this case we need directory to further proper images displaying
        this.directory = file.getParent();
        
        FileReader fr;
        try {
            fr = new FileReader(file);
            BufferedReader br = new BufferedReader(fr);
            String s;

            //adding atributes name to input pattern
            s = br.readLine();
            String[] tempAtributes = s.split(";");
            this.attributes.addAll(Arrays.asList(tempAtributes));

            //geting weight vector
            while((s = br.readLine()) != null){
                String[] vectorText = s.split(";");
                
                for(int i=0; i<vectorText.length; i++){
                    this.vector.add(Double.parseDouble(vectorText[i]));
                }
            }

            fr.close();
            
        } catch (FileNotFoundException e) {
            System.out.println("Such file does not exist.");
        } catch (IOException e) {
            System.out.println("Could not read the file.");
        }
    }
    
    @Override
    public ArrayList<Double> getVector() {
        return vector;
    }
    
    public ArrayList<String> getAttributes() {
        return attributes;
    }


    public String getDirectory() {
        return directory;
    }

    public String getFileName() {
        return fileName;
    }
}

public interface DataLoader {   
    public ArrayList<InputPattern> getData();
}

public class DataLoaderICPR1 implements DataLoader{

    private ArrayList<InputPattern> data = new ArrayList<InputPattern>();
    
    public DataLoaderICPR1 (String path){
        Collection<File> allPaths = new ArrayList<File>();
        addFilesRecursively(new File(path), allPaths);
        
        Iterator<File> iter = allPaths.iterator();
        while(iter.hasNext()){
            File file = (File) iter.next();
            if(file.isFile()){
                try {
                    String pathToFile = file.getCanonicalPath();
                    InputPattern inputPattern = new InputPatternICPR1(pathToFile);
                    this.data.add(inputPattern);
                    
                } catch (IOException ex) {
                    Logger.getLogger(DataLoaderICPR1.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }

    }
    
    @Override
    public ArrayList<InputPattern> getData() {
        return data;
    }

    private static void addFilesRecursively(File file, Collection<File> all) {
        File[] children = file.listFiles();
        if (children != null) {
            for (File child : children) {
                all.add(child);
                addFilesRecursively(child, all);
            }
        }
    }

Opisowo słownie o co chodzi. Mamy Interfejs to danych i klasę to odczytywania tych danych. W tej klasie do odczytywanie metoda getData() zwraca nam ArrayList<InputPattern>. Natomiast samo przypisanie obiektów do tej listy wygląda w następujący sposób:

InputPattern test = new InputPatternICPR(argument);
this.lista.add(test); 

Jeszcze na dodatek w InputPattern mamy metodę getVector, która zwraca ArrayList<Double>.

No i do puenty. Mam jeszcze jedną klasę, która w konstruktorze jako argument przyjmuje DataLoader. I tam się dokonują pewne obliczenia (sama data nie jest zmieniana). Po prostu na podstawie danych z getVector obiekt InputPattern jest przypisywany do obiektów w przestrzeni (kolejna ArrayLista ale już inny obiekt). Po tych wszystkich obliczeniach itd. potrzebuje się dostać do pewnych metod specyficznych dla InputPatternICPR. a nie InputPattern. Mogę to robić jawnie rzutując, np,:

        ArrayList<InputPattern> test = dane.getData();

        InputPatternICPR1 test2 = (InputPatternICPR1)test.get(0);       

Tylko czy to jest dobra rozwiązanie?? Czy istnieje jakiś inny mechanizm.
P.S. sorki za długi post ale nie chciałem jak najdokładniej to wymyślić - program w starej wersji ma 3k linii kodu, a chcę przepisać od nowa i dodać więcej funkcjonaliści.

0

Może własne genericsy?

interface DataLoader<T extends InputPattern>{
   List<T> getData();
}

I potem można stworzyć klasę:

public class DataLoaderICPR1 implements DataLoader<InputPatternICPR1>{
//....
}

Wtedy getData zwróci listę w pożądanym typie...

0

Jest to jakiś pomysł, ale co jak mam gdzieś coś takiego:

 
public class Unit {  
    private ArrayList<InputPattern> inputPatternMapedOntoUnit = new  ArrayList<InputPattern>();
    
    public addMapped(InputPattern ip){
        this.inputPatternMapedOntoUnit.add(ip);
    }

    public ArrayList<InputPattern> getInputPatternMapedOntoUnit() {
        return inputPatternMapedOntoUnit;
    }
}

I teraz właśnie to o czym mówiłem do obliczeń jest w sumie potrzebny mi tylko wektor ale już po obliczeniach mam Unit który zawiera listę InputPattern zmapowanych jednostek. I chcę sobie coś takiego zrobić:

 
ArrayList<InputPatternICPR1> lista = unit.getInputPatternMapedOntoUnit();
lista.get(0).getFileName();

Nie zadziała bo niekompatybilny typ. Tylko rzutowanie pomoże.

Generalnie chodzi o to: Mamy pliki tekstowe z danymi. Jak wiadomo natura danych jest przeróżna. Ale w każdym z tych plików jest wektor i inne rzeczy. Mogę w pamięci przechowywać wektor z innymi rzeczami, ale do obliczeń potrzebna mi uniwersalna metoda, która w sumie tylko korzysta z wektora. Natomiast po obliczeniach i mapowaniu potrzebne mi są pewne rzeczy, które zawsze dopisuje (tzn. dataLoader chodzi zawsze w parze z inputPattern i jeszcze dodatkowo obróbka po obliczeniach nie jest automatyczna - sam będę dopisywał za każdym razem jak się zmienią dane) właśnie oprócz wektora, takie jak: fileName, atrybuty, itd., które oprócz wektora są zapisane w pliku tekstowym z danymi. Po co: bo na końcu po obliczeniach generuje XML'a i potrzebne mi są te wszystkie właściwości. Czyli jak piszę DataLoadera to piszę też InputPattern nowego i XMLGenerator nowego. Może to bardziej objaśni sprawę czy trzeba zmieniać mój pomysł czy programować tak jak to na początku wymyśliłem z jawnym rzutowaniem :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1