Newsgroup: it.comp.java
Titolo: Parametrizzare tipi da stringa

Ho un problema che spero possa trovare soluzione (certamente dettato
dall'ignoranza)
Supponiamo di avere tre classi che contengono diversi oggetti:
Articoli
Fonitori
Clienti
Ognuna delle tre classi eredita un metodo "findAll" che ritorna una
lista per cui posso scrivere
Articoli A = new Articoli();
List tutti = A.findAll();
Ora ho i nomi delle tre classi come stringhe, tipo:
String S1="Articoli";
String S2="Fornitori";
String S3="Clienti";
Come posso fare a riferirmi alle stringhe per usare la classe giusta?
Per fare un esempio (ovviamente non funzionante) vorrei poter scrivere
Sx A = new Sx();
List tutti = Sx.findAll();
passando come parametro a Sx la stringa che rappresenta la classe
diversa. (in modo da non riscrivere n volte le stesse cose)
Come fare?


Reflection?
http://www2.mokabyte.it/cms/article.run?articleId=FKB-LTL-5BX-YD5_7f000001_7470813_658e54b3
 

 Come posso fare a riferirmi alle stringhe per usare la classe giusta?
Class.forName(stringa).newIstance();
permettimi però di obiettare sull'uso/abuso di questa tecnica
nell'esempio da te postato.
è utile se le tre classi implementano la stessa interfaccia o derivano
dalla stessa classe astratta, altrimenti la logica hard-coded la
sposti solamente un po' più in là.


Vorrei ringraziarvi tutti, in particolare toto per il link sulla
reflection.
E' vero che questo approccio funziona bene quando le classi hanno
metodi sostanzialmente uguali tra le classi, altrimenti com dice
rootkit la cosa diviene ancora più dura.
Ma con la reflection riusciremo a programmare meno, anche quando
verranno stravolte le tabelle DB a cui puntiamo con il nuovo codice
"riflesso".
Grazie ancora!

 "riflesso".
Da quali modifiche al DB il tuo codice sarebbe immune?
Forse dovresti considerare gli ORM e/o il pattern DAO prima di 
reinventare la ruota.
La strada per programmare meno si chiama riuso del software e passa dal 
conoscere le soluzioni già esistenti (come librerie e design pattern), e 
non necessariamente dalla meta-programmazione.
-- 
Andrea Francia
http://andreafrancia.blogspot.com/2008/06/relazioni-molti-molti-con-jpa.html

 "riflesso".
mah.
le tue affermazioni mi convincono poco, in ogni caso saprete voi cosa 
state facendo. in bocca al lupo.
-- 
? Fino all'anno scorso avevo un solo difetto. Ero presuntuoso.
http://softvalley.blogspot.com
http://www.flickr.com/photos/marko_po/

Nardone ha scritto:

Io non ho capito cosa vuoi evitare e cosa devi fare...dimentica 
reflection, stringhe ecc...quale e' il problema originario?


Ora ho capito megliio...
Vista la tua dichiarata inesperienza e' *probabile* che tu ti stia
smazzando su qualcosa di completamente inutile.
Potevi invece fare in gran velocita' una cosa come questa
public class MiaFactory {
  public static InterfacciaComune getInstance(String name) {
    if ("articoli".equals(name)) {
      return new Articoli();
    } else if ("pippo".equals(name)) {
      return new Pippo();
    }
    ...
    throw new IllegalStateException(name +" non contemplato.");
  }
}
Funziona, non ha seghe mentali ed e' pure mantenbile.

 
Per quanto riguarda la soluzione che hai esposto non riesco a 
commentarla dal punto di vista generale perché non credo di aver capito 
qual'e' il problema che l'OP voleva risolvere.
-- 
Andrea Francia
http://www.andreafrancia.it/

 Funziona, non ha seghe mentali ed e' pure mantenbile.
il problema suo è che manca quella "InterfacciaComune".
perchè altrimenti la soluzione di istanziare dinamicamente le classi
sarebbe tutt'altro che una sega mentale, anzi, devo dire che la tua
soluzione mi schifa abbastanza di più :-) mi sta bene usare il
factory, ma a quel punto perchè usi i tipi cablati che ti obbligano ad
averli noti in compilazione?

 averli noti in compilazione?
La complessita' si riduce a 3 if che non diventeranno mai 100 o 1000.
E se mai dovesse accadere e' meglio appoggiarsi a un IoC container
perche' tanto con il tuo frameworkino fatto in casa non vai da nessuna
parte.
Il discorso dei cablati noti in compilazione non l'ho capito..dove
starebbe il problema? Il punto debole della mia soluzione (bada bene
che mi riferisco solo a questo semplicissimo contesto, altrimenti ne
avrebbe ben altri) sono i 3 if...

 suddetto.
non c'è bisogno di aggiungere complessità per istanziare una classe
dal suo nome.
mappando i classname in un resource bundle il tutto si riduce a due
righe di codice. con i vantaggi:
1 - ottieni l'astrazione desiderata
2 - non hai bisogno di conoscere i tipi a compiler time
3 - il giorno che hai una nuova classe non metti mano al codice
4 - i factory servono a questo :-)

 starebbe il problema?
nessun problema, semplicemente completi il disaccoppiamento insito
nell'implementazione di un factory.

 nell'implementazione di un factory.
Ah beh...chiaro adesso.

 
certo, a creare oggetti, ma non dicono come.
Io dico che finche' il problema e' cosi' semplice va benissimo anche 
piazzare un paio di if dentro una factory, mentre al crescere della 
complessita' si passa subito a qualcosa come Spring. Senza soluzioni 
intermedie (properties ecc..).
Questo per chi non consoce Spring, perche' io e te iniziamo 
tranquillamente in ogni caso con Spring (o altro), giustamente.

 intermedie (properties ecc..).
tendenzialmente la penso in modo diverso, cioè non mi piacciono le 
soluzioni "per ora va bene così, poi vediamo". anche perchè non ci sono 
soluzioni più definitive di quelle temporanee :) per esperienza, prevedo 
che al crescere della complessità aumenteranno solo le if.
se una soluzione costa poco ed è un po' più lungimirante rispetto alla 
esigenza immediata secondo me va applicata; poi si può discutere se 
parametrizzare in un file di properties o da qualche altra parte, ma se 
lui si è posto il problema di parametrizzare la creazione delle classi il 
sospetto che sotto sotto stia cercando un sistema "espandibile" viene. 
altrimenti non avrebbe alcun senso nemmeno la domanda, o meglio, verrebbe 
da rispondere: perchè parametrizzare la creazione di tre classi in 
croce? :)

 che al crescere della complessità aumenteranno solo le if.
Non volevo continuare il thread, anche perche' stai esponendo opinioni
che non posso dire sbagliate.
Tuttavia, nella mia esperienza di programmatore, ho imparato a non
buttarmi quasi mai in soluzioni del genere, e cercare di essere il
piu' concreto possibile.
Alla prima difficolta' (ad esempio voler far qualcosa di piu' di un
new Articoli(), magari iniettando dipendenze o che so..comunque sono
cose piuttosto probabili) hai 2 strade:
-prepararti a scrivere il tuo mini framerwork (e devi avere valide
ragioni per fare cio', oltre che capatia', tempo e voglia)
-usare un framework esistente (e quindi risulta inutile la strada
intrapresa prima, o meglio sicuramente non superiore ai 3 if
dell'esempio).
In questo senso i 3 IF sono solo *apparentemente* una soluzione meno
elegante del properties.