Verschachtelte Generics

  • Themenstarter Themenstarter Guest2
  • Beginndatum Beginndatum
G

Guest2

Gast
Moin,

ich schreibe aktuell an einer Bibliothek, mit einer Klassenstruktur, die sehr stark gekürzt und in ein KSKB gepresst etwa so aussieht:

Java:
package test;


public class KSKB {

    interface ASMBuffer<T> { }

    interface GLBuffer<T> extends ASMBuffer<T> { }

    static class ASMSampleBuffer<T> implements ASMBuffer<T> { }

    static class GLSampleBuffer<T> extends ASMSampleBuffer<T> implements GLBuffer<T> { }

    
    static class GLPointerBuffer<T extends ASMBuffer<?>> extends ASMSampleBuffer<T> implements GLBuffer<T> {

        @SafeVarargs
        public GLPointerBuffer(final T... values) {  }

    }
    
    
    @SafeVarargs
    static <T extends ASMBuffer<?>> GLPointerBuffer<T> bar(final T... values) {

        return new GLPointerBuffer<T>(values);

    }


    static void foo(final ASMBuffer<ASMBuffer<Character>> value) {

    }


    public static void main(final String[] args) {

        // Geht:
        final GLBuffer<ASMBuffer<Character>> v1 = new GLPointerBuffer<ASMBuffer<Character>>(new GLSampleBuffer<Character>());
        foo(v1);
        
        
        // Geht:
        foo(KSKB.<ASMBuffer<Character>> bar(new GLSampleBuffer<Character>()));

        
        // Geht nicht:
        final GLBuffer<GLBuffer<Character>> v2 = new GLPointerBuffer<GLBuffer<Character>>(new GLSampleBuffer<Character>());
        foo(v2);
        // The method foo(KSKB.ASMBuffer<KSKB.ASMBuffer<Character>>) in the type KSKB is not applicable
        // for the arguments (KSKB.GLBuffer<KSKB.GLBuffer<Character>>)
        
        
        // Geht nicht:
        final GLBuffer<GLBuffer<Character>> v3 = new GLPointerBuffer<>(new GLSampleBuffer<Character>());
        // Type mismatch: cannot convert from KSKB.GLPointerBuffer<KSKB.GLSampleBuffer<Character>> to
        // KSKB.GLBuffer<KSKB.GLBuffer<Character>>
        
        
        // Geht nicht:
        final GLBuffer<ASMBuffer<Character>> v4 = new GLPointerBuffer<>(new GLSampleBuffer<Character>());
        // Type mismatch: cannot convert from KSKB.GLPointerBuffer<KSKB.GLSampleBuffer<Character>>
        // to KSKB.GLBuffer<KSKB.ASMBuffer<Character>>
        
         
        // Geht nicht:
        foo(KSKB.bar(new GLSampleBuffer<Character>()));
        // The method foo(KSKB.ASMBuffer<KSKB.ASMBuffer<Character>>) in the type KSKB is not applicable
        // for the arguments (KSKB.GLPointerBuffer<KSKB.GLSampleBuffer<Character>>)

    }

}

Das, was in den Zeilen 39 bis 44 passiert, ist das was ich will und funktioniert so auch. Das Problem dabei ist, dass alle "ASM"-Klassen eigentlich interne Klassen sind. Diese bilden ein für sich abgeschlossenes (Maven-)Modul. Der Nutzer der Bibliothek soll sich nach Möglichkeit nicht mit diesen internen Klassen beschäftigen müssen.

Die Signatur von foo() kann ich auch nicht ändern, da diese auch von nicht "GL"-Klassen aufgerufen werden können muss. Außerdem liegt foo() eigentlich ebenfalls in einem eigenen Modul, zu dem ich keine weiteren Abhängigkeiten hinzufügen will. Das Modul von foo() kennt also kein "GL".

Meine Frage ist nun: Sieht jemand vielleicht eine Möglichkeit, wie das, was in den Zeilen 39 bis 44 passiert, formuliert werden kann, ohne explizit ASMBuffer hinschreiben zu müssen.

Viele Grüße,
Fancy
 
Ich glaube, du vermanschst hier die Generics ganz gewaltig. Was soll dein [c]T[/c] sein? Eigentlich doch der im Buffer gespeicherte Typ, also z.B.
Code:
Character
. Dann macht aber sowas wie [c]GLBuffer<GLBuffer<Character>>[/c] keinen Sinn, und erst recht nicht [c]GLPointerBuffer<T extends ASMBuffer<?>>[/c] - das wären dann ja Buffer von Buffern, und das willst du hoffentlich nicht. Ich könnte mir vorstellen, das du vielleicht sowas in der Richtung willst:

Java:
    class GLPointerBuffer<T, B extends ASMBuffer<T>> extends ASMSampleBuffer<T> implements GLBuffer<T> {
 
        @SafeVarargs
        public GLPointerBuffer(final B... values) {  }
 
    }

Oder wenn du nicht so genau wissen musst, was der übergebene Buffer-Typ ist, reicht vielleicht sogar schon:

Java:
    class GLPointerBuffer<T> extends ASMSampleBuffer<T> implements GLBuffer<T> {
 
        @SafeVarargs
        public GLPointerBuffer(final ASMBuffer<T>... values) {  }
 
    }


Aber das ist nur geraten.

Was klar ist, ist das wenn du einerseits den Werte-Type ([c]Character[/c]) und andererseits z.B. einen unterliegenden oder internen Buffer-Typ (wie [c]ASMBuffer[/c]) hast, dass du nicht beide "an der gleiche Stelle" als Typ-Parameter haben kannst. Ob meine Idee von oben richtig ist, kann ich nicht sagen, ohne mehr über die "Familienverhältnisse" und Ideen hinter den Buffern zu wissen.
 
Zuletzt bearbeitet:
Danke Dir für Deine Antwort! Die hat mich ein wenig in die Richtung geschubst, die ich brauchte.

Ich brauche aber tatsächlich "Buffer die Buffer enthalten". Der Hintergrund ist einfach, dass ich native Funktionen abbilden will, die als nativen Parametertyp z.B. "GLchar** pointer" haben (**!). Durch die Konstruktion mit dem [c]GLPointerBuffer<T extends ASMBuffer<?>>[/c] kann ich tatsächlich z.B. folgendes schreiben:

Java:
GLBuffer<Character> string1 = new GLStringBuffer(source1);
GLBuffer<Character> string2 = new GLStringBuffer(source2);
GLBuffer<GLBuffer<Character>> pointer = new GLPointerBuffer<>(string1, string2);
        
gl.glShaderSource(.., pointer,..);

Nativ liegt an der Adresse des GLPointerBuffers nacheinander die beiden Adressen der übergebenen GLStringBuffer. Damit der Compiler das annimmt, musste ich bisher [c]GLBuffer<ASMBuffer<Character>> pointer = ...[/c] schreiben. Beim aufräumen der API störte mich aber immer die Erwähnung des ASMBuffer.

Jetzt ist die Lösung inzwischen aber eigentlich ziemlich simpel, ich habe die Signatur von foo() (bzw. glShaderSource) einfach auf [c]foo(final ASMBuffer<? extends ASMBuffer<Character>> pointer)[/c] geändert (Bei den Buffern ist alles gleich geblieben.). Dadurch gibt der sich nun auch mit [c]GLBuffer<GLBuffer<Character>> pointer[/c] zufrieden. Hätte ich eigentlich auch vorher drauf kommen können. 😳

Dank und Grüße
Fancy
 

Zurück
Oben