Avatar billede jespersahner Nybegynder
13. maj 2006 - 09:12 Der er 13 kommentarer og
1 løsning

Constructor overloading og generics

Jeg forsøger at bruge flg. constructors:

MyClass(ArrayList<X> x) {
...
}

MyClass(ArrayList<Y> y) {
...
}

- men dette kompilerer ikke pga. overlap.

Hvordan løser man dette?
Avatar billede nielle Nybegynder
13. maj 2006 - 09:34 #1
Når compileren ikke tillader det, så er det nok ikke muligt at gøre så meget ved det.

Årsagen skyldes at begge constructore - undervejs i kompileringen - reduceres til:

    MyClass(ArrayList z) {
    }

Dvs. at de har det samme "erasure".

Problemet er i øvrigt ikke specifikt for constructore - f.eks. får du akurat samme fejlbesked med:

    public void demo(ArrayList<X> x) {
    }

    public void demo(ArrayList<Y> y) {
    }

Da fejlen altså skyldes at begge funktionere reduceres til identiske funktions-signature, kunne en mulig workaround være at ændre på den overordnede signatur:

    MyClass(ArrayList<X> x) {
    }

    MyClass(ArrayList<Y> y, boolean dummy) {
    }

- hvor dummy så bare ignoreres.
Avatar billede snoop_one Nybegynder
13. maj 2006 - 10:46 #2
Er der nogen sammenhæng mellem x og y ret polymorfisk?
Avatar billede mikkelbm Nybegynder
13. maj 2006 - 10:47 #3
Som nielle siger, er det ikke muligt, da generics i Java bare bliver lavet om til Object som så parses/castes til den type du angiver.

Jeg har ikke en umiddelbar løsning - dog bryder jeg mig ikke om den dummy-variable :)
Avatar billede jespersahner Nybegynder
13. maj 2006 - 11:19 #4
Kan man ikke bruge "generic methods"?

Flg. virker:
public <T> void method(T x) {
...
}
public <T extends String> void method(T y) {
...
}

Men flg. virker ikke:
public <T extends ArrayList<String>> method(T s) {
...
}

public <T extends List<Integer>> method(T i) {
...
}

Der er vel umiddelbart (ikke gennemtænkt!) en slags modstrid i, at man med generics netop specificerer/indsnævrer over for compileren på compile-time, hvad man ønsker, men at man omvendt ikke kan lave simpel overload som ovenfor, hvor man jo netop gør "en dyd ud af" at understrege forskellen mellem metoderne.
Avatar billede nielle Nybegynder
13. maj 2006 - 11:24 #5
Disse to:

public <T extends ArrayList<String>> method(T s) {
}

public <T extends List<Integer>> method(T i) {
}

- vitrketr ikke af den simple grund at der ikke skelnes til retur-værdien når det skal afgøres om der er tale om to overloads:

De opfattes begge to som:

public XXX method(T s) {
}

public XXX method(T i) {
}

- og så er deres signature jo ens.
Avatar billede jespersahner Nybegynder
13. maj 2006 - 11:30 #6
Sludrer lige lidt videre..

Problemet er ikke så stort ved metoder, idet man helt banalt kan give metoderne forskellige navne demoX() og demoY(). Med constructors er navnet jo givet, så her er det lidt vanskeligere. At tilføje en ekstra parameter virker jo, men er ikke pænt. En variant kunne måske være noget med at erstatte constructors af static metoder, der returnerer et objekt af klassen, og disse metoder kan man så give forskellige navne, altså:

class MyClass {

  public static MyClass demoX() {
  ...
  }

  public static MyClass demoY() {
  ...
  }

}

MyClass x=MyClass.demoX();
MyClass y=MyClass.demoY();
Avatar billede jespersahner Nybegynder
13. maj 2006 - 11:33 #7
->nielle: Det er vel ikke rigtigt.

Flg. virker:
public <T> void method(T x) {
...
}
public <T extends String> void method(T y) {
...
}

Begge metoder har samme returtype (void), men genrics er her en del af signaturen, som jeg forstår det.
Avatar billede nielle Nybegynder
13. maj 2006 - 11:43 #8
Du har ret.

Grunden til at dette ikke virker:

public <T extends ArrayList<String>> method(T s) {
}

public <T extends List<Integer>> method(T i) {
}

- er at <T extends ArrayList<String>> og <T extends List<Integer>> slet ikek fungere som returtyper i det givne tilfælde - de er derimod en del af den overordnenede syntaks. Derfor fejler kompileringen af den simple grund at dine metoder ikke har nogen retur-type.
Avatar billede jespersahner Nybegynder
13. maj 2006 - 12:09 #9
->nielle: Nej, du misforstår mig, fordi jeg skrev noget vrøvl (havde constructors i tankerne, dvs. ingen returtype og skrev også List i st. f. ArrayList).

Forhåbentlig mere præcist:

1. Flg. virker:
public <T> void method(T x) {
...
}
public <T extends String> void method(T y) {
...
}

2. Flg. virker IKKE:
public <T extends ArrayList<String>> void method(T s) {
...
}

public <T extends ArrayList<Integer>> void method(T i) {
...
}

Spørgsmålet er, om det sidste kan bringes til at virke (?)
Avatar billede nielle Nybegynder
13. maj 2006 - 12:11 #10
Det kan jeg vist desværre ikke rigtigt svare på :^|
Avatar billede nielle Nybegynder
13. maj 2006 - 12:15 #11
Og dog, svaret er det samme som i 13/05-2006 09:34:33:

Metoderne:

    public <T extends ArrayList<String>> void method(T s) {
    }

    public <T extends ArrayList<Integer>> void method(T i) {
    }

bliver begge to reduceret til:

    public <T extends ArrayList> void method(T s) {
    }

    public <T extends ArrayList> void method(T i) {
    }

i forbindelse med kompileringen. Derfor samme signatur.
Avatar billede nielle Nybegynder
25. maj 2006 - 22:53 #12
Var der ellers mere?
Avatar billede jespersahner Nybegynder
26. maj 2006 - 12:48 #13
->nielle: Nej, det er fint. Smid gerne et svar :-)
Avatar billede nielle Nybegynder
26. maj 2006 - 16:35 #14
Ok, men jeg var bare ikke sikker på at du havde fået svar på alle dine spørgsmål...

Svar :^)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester