metoda z parametrem generycznym

0

Witam z klasami generycznymi nie miałem za dużo wspólnego ale zdaje mi się że by mi pomogły z moim problemem. A mianowicie mam problem z moim interfejsem File który odpowiada za zapisanie do pliku i odczytanie z pliku danych. Problemem jest zapis, bo w parametrze mam User user a dopiero późnej przypomniałem sobie że w klasie TxtFile parametrem będzie arraylist. Chciałem zrobić generyczny parametr np . public void write(<T> T) ale nie działa.

package pl.nbp.model.filehandler;

import pl.nbp.model.User;

import java.io.IOException;
import java.util.ArrayList;

import static javafx.scene.input.KeyCode.T;

public interface File {

    public void isExist() throws IOException;

    public void isEmpty() throws IOException;

    public ArrayList read() throws IOException;

    public void write(User user) throws IOException; // tu chce zrobić tak ze jak podam write(user) lub write(jakiś string) to by to działało

    public void createEmptyFile() throws IOException;

    public void addFileHeader() throws IOException;
}

0

Typy generyczne trzeba deklarować przed ich podaniem:

<T> void write(T element) throws IOException; // tu chce zrobić tak ze jak podam write(user) lub write(jakiś string) to by to działało

Ewentualnie możesz przeładować operator, tj.

void write(User user) throws IOException;
void write(String string) throws IOException;

I tak już z boku - "public" w interfejsach nie jest wymagane.

0

Ok ma pytanie jak stosuje twoje pierwsze podejście to mam problem później dostać się do pól które siedzą w klasie user np. getFisrtName nie wiem jak dostać się do niech z Object element ? Może masz jakieś na to rozwiązanie. A co dwóch pozostałych przypadków to w każdej klasie która będzie implementować File będę musiał oby dwie te metody implementować? Czy może jest jakoś opcja na to ? Ja rozwiązałem to w ten sposób że dodałem generyczną arrayList i działa. Ale nie wiem czy moje rozwiązanie jest eleganckie

0

Czemu stosujesz nazwe swojego interfejsu zgodną z nazwą jednej z kluczowych klas Javy SE https://docs.oracle.com/javase/8/docs/api/java/io/File.html?

0
87kelthuzad napisał(a):

Ok ma pytanie jak stosuje twoje pierwsze podejście to mam problem później dostać się do pól które siedzą w klasie user np. getFisrtName nie wiem jak dostać się do niech z Object element ? Może masz jakieś na to rozwiązanie. A co dwóch pozostałych przypadków to w każdej klasie która będzie implementować File będę musiał oby dwie te metody implementować? Czy może jest jakoś opcja na to ? Ja rozwiązałem to w ten sposób że dodałem generyczną arrayList i działa. Ale nie wiem czy moje rozwiązanie jest eleganckie

A jak chcesz użyć metody getFirstName w Stringu? A jak w jakiejkolwiek klasie dziedziczącej po Object? Innymi słowy - skąd kompilator ma wiedzieć, jaka klasa tam naprawdę trafi? Generyki tak nie działają.

Jak chcesz zbiór klas które implementują/dziedziczą po User, to robisz np. tak


interface File<T extends User>{
    public void write(T user)
}

I wtedy będziesz mógł wywołać metodę "getFisrtName " z Usera. Używanie generyków do Stringów i do Usera nie ma sensu, jeśli chcesz użyć metody z Usera, bo to dwa zupełnie róże obiekty.

A co do drugiego pytania:

Unless the class that implements the interface is abstract, all the methods of the interface need to be defined in the class.

I jestem ciekaw co to za rozwiązanie z ArrayListą...

EDIT:
Jak się uprzesz to możesz zrobić coś takiego:

    @Override
    public void write(Object a) {
        if ( a instanceof User ){
            User b = (User) a;
            b.foo();
        }
    }

Ale to raczej bezsensu.

0

interfejs File

void write(ArrayList<E> E) throws IOException;

klasa CsvFile

 public void write(ArrayList E) throws IOException {
        ArrayList<User> newUserTowrite = E;
        System.out.println(newUserTowrite.toString());
        isExist();
        isEmpty();
        fileWriter = new FileWriter(PATH_TO_USER_FILE, true);
        fileWriter.append(String.valueOf(newUserTowrite.get(0).getId()));
        fileWriter.append(COMMA_DELIMITER);
        fileWriter.append(newUserTowrite.get(0).getFirstName());
        fileWriter.append(COMMA_DELIMITER);
        fileWriter.append(newUserTowrite.get(0).getLastName());
        fileWriter.append(COMMA_DELIMITER);
        fileWriter.append(newUserTowrite.get(0).getLogin());
        fileWriter.append(COMMA_DELIMITER);
        fileWriter.append(newUserTowrite.get(0).getPassword());
        fileWriter.append(NEW_LINE_SEPARATOR);
        fileWriter.close();
        newUserTowrite.clear();
    }
0

Zobacz co jest możliwe używając twojej funkcji, wszystko się kompiluje, niby wszystko ok.

 void name() {
        ArrayList x = new ArrayList();
        x.add("a");
        x.add("b");
        x.add("c");
        t.write(x);
    }


 public void write(ArrayList E) throws IOException {
        ArrayList<User> newUserTowrite = E;
        (...)
        System.out.println(newUserTowrite.get(0).getId());
        (...)
    }

A po uruchomieniu programu?

java.lang.ClassCastException: java.base/java.lang.String cannot be cast to User

Czemu?
Bo robisz unchecked cast (niejawne rzutowanie?) i Twoje obejście tylko sprawia, że umożliwiasz powstawanie takich błędów. Java jest po to silnie typowana, by takich problemów unikać.

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