2016-05-10 6 views
5

Was ich will, ist folgende:Infer generische Klasse Typ Parameter von einzelnen Konstruktorparameter

Die meiste Zeit wird die generische Klasse wie TestBuilder<X, X> sein, was bedeutet, dass T und O des gleichen Typs sind. Deshalb erstelle ich zwei verschiedene Konstruktoren. Ich möchte anonyme neue Anrufe wie new TestBuilder<>(...) machen (ich rufe die <> anonoumous hier).

folgenden 4 Konstruktor Beispiel existiert:

1) Arbeits Konstruktor ruft

// Anonoumous, working 
new TestBuilder<>(String.class, Integer.class) 
    .withOnNext(new Action1<Integer>() 
    { 
     @Override 
     public void call(Integer integer) 
     { 
     } 
}); 

// not anonoumous, classified, working 
new TestBuilder<String, String>(String.class) 
    .withOnNext(new Action1<String>() 
    { 
     @Override 
     public void call(String string) 
     { 
     } 
}); 

2) Konstruktoraufrufe mit Problemen oder arbeiten nicht

// Anonoumous and working 
// PROBLEM: withOnNext is called with Object instead of String 
new TestBuilder<>(String.class) 
    .withOnNext(new Action1<Object>() 
    { 
     @Override 
     public void call(Object o) 
     { 
     } 
}); 

// Anonoumous and NOT working 
// this is what I want to work! 
new TestBuilder<>(String.class) 
    .withOnNext(new Action1<String>() 
    { 
     @Override 
     public void call(String string) 
     { 
     } 
}); 

Frage

Gibt es eine Möglichkeit, den 4. Konstruktor zum Laufen zu bringen? Ich möchte nicht gezwungen werden, dem Konstruktor zwei Klassen zu geben, wenn ich es nur mit einem Argument anrufe, die zweite generische Klasse sollte in diesem Fall von der ersten "erben". Anstatt new TestBuilder<String, String>(String.class) schreiben zu müssen, möchte ich schreiben new TestBuilder<>(String.class) oder zumindest new TestBuilder<String>(String.class) ...

Klasse

Dies ist, was die Test-Builder-Klasse wie folgt aussieht:

public class TestBuilder<T, O> 
{ 
    public TestBuilder(Class<T> eventClass) 
    { 
     this(eventClass, (Class<O>)eventClass); 
    } 

    private TestBuilder(Class<T> eventClass, Class<O> observableClass) 
    { 
     init(); 
    } 

    public TestBuilder<T, O> withOnNext(Action1<O> actionNext) 
    { 
     mActionNext = actionNext; 
     return this; 
    } 
} 
+0

Klasse hat bestimmt/gegeben werden, oder es wird auf die 'Object' Typ Standard. Eine Abhilfe setzt in generischen Typen (Konstruktor 2) oder Gießen. Was ist schlimmer als Eingabe generische Typen. Eine Möglichkeit könnte auch der private Konstruktor sein. Obwohl das den Zweck dieses ganzen Mechanismus besiegen würde. – n247s

+0

verwenden Sie tatsächlich die '' 'Klasse <...>' '' Objekte, die Sie weitergeben? –

+0

Die erste 'Klasse <...>' Objekt verwendet wird, die zweite ist für die generische Klasse Bestimmung nur ... – prom85

Antwort

2

ich glaube nicht, Java den zweiten generischen Typen ableiten kann wi eine Art Hinweis. Eine Möglichkeit besteht darin, dem Typ eine Variablendeklaration zu geben:

TestBuilder<String, String> testBuilder = new TestBuilder<>(String.class); 
testBuilder.withOnNext(new Action1<String>() { 
    @Override 
    public void call(String string) { 
     //... 
    } 
}); 

Sie müssten jedoch beide generischen Parameter deklarieren.

Was ich tun würde, ist die Information einkapseln, dass sowohl T und O das gleiche in einer statischen Factory-Methode sind:

public class TestBuilder<T, O> { 
    public static <T> TestBuilder<T, T> create(Class<T> eventClass) { 
     return new TestBuilder<T, T>(eventClass); 
    } 
    // ... 
} 

und dann rufen Sie wie folgt aus:

TestBuilder.create(String.class).withOnNext(...); 

eine weitere Option ist Einkapseln der Informationen in einer separaten Klasse erbt von TestBuilder:

public class SimpleTestBuilder<T> extends TestBuilder<T,T> { 
    public SimpleTestBuilder(Class<T> eventClass) { 
     super(eventClass, eventClass); 
    } 
} 

public class TestBuilder<T, O> { 
    private TestBuilder(Class<T> eventClass, Class<O> observableClass) { 
    } 
    // ... 
} 

Eingesetzt als

new SimpleTestBuilder<>(String.class).withOnNext(...); 

Noch eine weitere gute Möglichkeit ist, die Informationen O sind die gleichen wie T in einer statischen Methode zu kapseln:

public class TestBuilder<T, O> { 
    public static <T> TestBuilder<T, T> create(Class<T> eventClass) { 
     return new TestBuilder<T, T>(eventClass); 
    } 
    // ... 
} 

Eingesetzt als

TestBuilder.create(String.class).withOnNext(...); 
+0

Danke. Die statische create function Lösung ist eine Lösung, die ich mag, habe nicht darüber nachgedacht ... – prom85

0

Sie können eine Hilfstypvariable für das f einfügen rste Konstruktor wie folgt aus:

public class TestBuilder <T, O> 
{ 
    public <H extends T, O> TestBuilder(Class<H> c) 
    { 
     this((Class) c, (Class) c); 
    } 

    public TestBuilder(Class<T> c1, Class<O> c2) 
    { 
     // ... 
    } 

    public static void main(String[] args) 
    { 
     TestBuilder<String, String> hw = new TestBuilder<>(String.class); 
     System.out.println(hw); 
    } 
} 

Diese für den Konstruktor einige unchecked Warnungen erstellen, aber nicht an der Aufrufstelle. Bitte beachten Sie jedoch, dass einige dieser Ad Praxis betrachten könnte, zumal nicht jeder kennt Konstruktortyp Parameter. Aus Gründen der Vollständigkeit hat der expliziten Aufruf des Konstruktor wie folgt aussehen:

new<String> TestBuilder<>(String.class).doStuff() 
Verwandte Themen