2016-09-02 1 views
2

In meinem Code habe ich eine generische Container-Schnittstelle. Der Container hat ein Factory-Objekt und der Containertyp wird vom Werk festgelegt.Generische Container Fabrik

Wie so:

public class HardGenerics { 
    public static Container<String> stringContainer(Function<Supplier<String>,Container<String>> factory) { 
     return factory.apply(() -> ""); 
    } 

    public static Container<Integer> integerContainer(Function<Supplier<Integer>,Container<Integer>> factory) { 
     return factory.apply(() -> 0); 
    } 

    private interface Container<T> { } 

    public static class ListBackedContainer<T> implements Container<T>{ 
     private final Supplier<T> factory; 
     private List<T> list = new ArrayList<T>(); 
     public ListBackedContainer(Supplier<T> factory) { 
      this.factory = factory; 
     } 
    } 

    public static void main(String[] args) { 
     create(); 
    } 

    private static void create() { 
     stringContainer(ListBackedContainer::new);//extract single parameter 
     integerContainer(ListBackedContainer::new);//extract single parameter 
    } 
} 

Frage:

Ich möchte die Container Fabrik passieren (dh ListBackedContainer :: neu) um in meinem Code-Basis, aber ich kann nicht herausfinden, wie um es zu tippen?

Update:

So das Problem zu erarbeiten. Ich kann das nicht tun (oder ich kann nicht herausfinden, wie man):

public static void main(String[] args) { 
    create(ListBackedContainer::new); 
} 

private static void create(Function<Supplier</*what to do*/>, Container</*what to do*/>> factory) { 
    stringContainer(factory); 
    integerContainer(factory); 
} 

ich um eine abstrakte generische Container Fabrik passieren möchte, und nicht der Beton ListBackedContainer

+0

Was ist los mit dem, was Sie hier haben? – shmosel

+0

Wie Sie aus den beiden Kommentaren und meiner vorgeschlagenen Problemumgehung unten sehen können, möchte ich eine einzelne ContainerFactory übergeben, aber welcher Typ sollte es haben – mathiasbn

+0

Sorry, ich folge nicht. Warum ist 'containerFactory :: create 'besser als' ListBackedContainer :: new '? – shmosel

Antwort

2

Ich bin nicht sicher, dass es

public static void main(String[] args) { 
    create(ListBackedContainer::new); 
} 

private static void create(ContainerFactory containerFactory) { 
    stringContainer(containerFactory::create); 
    integerContainer(containerFactory::create); 
} 

interface ContainerFactory{ 
    <T> Container<T> create(Supplier<T> itemFactory); 
} 

Nicht viel Beinarbeit, und es ist ausdrucksvoller als gattungs Hölle: möglich, so dass eine angemessene Abhilfe könnte eine echte abstrakte Fabrik Schnittstelle wie so zu schaffen sein.

+0

auswählen Dies ist keine korrekte Lösung. 'ListBackedContainer :: new' ignoriert den' T'-Parameter der Fabrik und erzeugt eine Warnung vom Typ Rohteil. – shmosel

+0

Ich bin mir eigentlich nicht sicher, warum es diese Warnung generiert. Type-Inferenz funktioniert gut mit einer statischen Factory-Methode ('ListBackedContainer :: create'), schlägt aber mit der Konstruktorreferenz fehl. – shmosel

+0

Sie können die Warnung zu unformatierten Typen auch vermeiden, indem Sie die Factory als anonyme Unterklasse instanziieren, anstatt eine Methodenreferenz zu verwenden. Wenn Sie die Klasse speziell mit einer Methodenreferenz konstruieren möchten, können Sie eine Factory-Factory erstellen, die auch anonym instanziiert ist und 'ListBackedContainer :: new' zurückgibt. – shmosel