Zwracanie dynamicznie parametryzowanego interfejsu.

0

Witajcie, mam pewien problem, ktorego nie moge rozwiazac (moja wiedza z zakresu dzialania mechanizmu refleksji w Javie jest, jak widac, jeszcze zbyt nikla ;) ).

Otoz - jest sobie klasa K, ktora implementuje interfejs I, ktory jest parametryzowany typem T.

class K implements I<T> {...}

gdzie tym typem jest powiedzmy... T = Object.

Klasa K posiada metodę - "public I<?> zmieńInterfejs(String nazwaKlasy) {...}". Problem w tym, ze nie potrafie napisac dzialajacego kodu, ktory by zrealizowal moj zamysl, ktory najlepiej przedstawie w kodzie (ktory w Javie niestety nie przechodzi):

public I<?> zmieńInterfejs(String nazwaKlasy) {
  Class c = Class.forName(nazwaKlasy);
  return (I<c>)this; // c.getClass() i podobne wymysly nie dzialaja niestety
}

Pewnie zabralem sie ze zlej strony do problemu - generalnie chodzi mi o to, zeby:

  • klasa posiadala metody get i set, ktore dzialaja na jakims typie domyslnym (np. Object)
  • ale (z racji, ze w Javie nie ma czegos takiego, jak metody parametryzowne: metoda<Klasa>(argumenty) ) chciałbym mieć możliwość otrzymania interfejsu dla obiektu tej klasy, ktory by mi obslugiwal okreslony typ danych:
K k = new K();
...
(klasa K przechowuje obiekty roznych typow - i chcialbym, zeby get moglo zwracac elementy okreslonego typu w zaleznosci od tego, jaki "interfejs jest wybrany")
...
I<String> i = k.zmienInterfejs("java.lang.String");
String s = i.get(); // brak potrzeby rzutowania na String wyniku

Innymi slowy:
Wobrazmy sobie mapę Map<String, Object>. Wsadzamy tam obiekty: "Ala"=1, "Ela"="bla", ... (czyli roznych typow). A potem mamy metodę get(String klucz), ktora nam zwraca tylko obiekty o okreslonym typie (w zaleznosci od tego, jaki interfejs jest wybrany), czyli np:

I<Integer> i = obj.zmienInterfejs("java.lang.Integer");
Integer ala  = i.get("Ala"); // ok
Integer ela = i.get("Ela"); // wywala jakis moj wlasny wyjatek, ze takiego obiektu nie ma (bo typ jest niezgodny - tam byl String a tu jest potrzebny Integer)

Uff... mam nadzieje, ze ktos mnie zrozumie i ulzy mi w cierpieniu ;)

P.S.

Chyba, ze mnie ktos zbawi i powie, jak ominac w Javie brak metod parametryzowanych ? To by bylo najprostsze:

Integer ala = obj.get<Integer>("Ala");
Integer ela = obj.get<Integer>("Ela"); // rzuca wyjatkiem (moim) o braku takiego elementu z powodu niezgodnosci typow
String ela = obj.get<String>("Ela");

Od biedy istnieje cos takiego:

public Object get(Class c,  String key) {
...
}

ale to wymusza rzutowanie przy uzyciu (a ja chcialbym to miec w jak najprostrzej formie - bez rzutowania, etc):
String s = (String)obj.get(String.class, "Ela");
0

Jak to nie ma metod parametryzowanych?

    public static <V extends Runnable> V blabla(V argument) {
        argument.run();
        return argument;
    }

Problem w tym, że nie możesz dostać się do V.class ani też zrobić instanceof V, ponieważ w Javie mamy Type erasure. Jednak jeśli przekazujesz tą klasę to już wszystko masz.

package Main;

public class Main {

    public static <V> V blabla(Class<V> aClass) {
        if (aClass.isInstance(new Object())) {
            // mamy instanceof :)
        }
        return null;
    }

    public static void main(String[] args) {
        String blabl = blabla(String.class);
    }
}

Scala rozwiązuje problem poprzez umieszczenie informacji o typie w manifeście wewnątrz sparametryzowanej klasy. Generalnie to nawet raczej dałoby się w niej zaimplementować tą metodę zmieńInterfejs.

0

A byłem święcie przekonany, że w Javie nie ma takich metod - przez to nawet nie szukalem informacji o nich... ech :/

Dzieki wielkie ! Uratowales mi skore ;]

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