Quique..
Se tiene este caso....
Code: Select all
+---------+
|TDataBase|
| |
+---+-----+
|
+---------+
| TData |
| |
+---+-----+
|
+------------+-------+------+-------------+
| | | |
+----+----+ +---+-----+ +----+----+ +---------+
| TCientes| |TFacturas| | TRecibos| | T... |
| | | | | | | |
+---------+ +---------+ +---------+ +---------+
Como comprenderas las classes hijas heredan de datas y metodos de la clase padre y tambien tienen data y metodos propios.
(ojo que, en este caso, la TDataBase no es la original de FW, tiene sus agregados, datas y metodos mas o menos complejos)
Ademas las clases hijas son en lo posible abtractas, e decir, no hacen referencia a modo de acceder a los datos (alias, area, field, etc.).
Lo que se pretende es querer tener la posibilidad de trabajar con otros modos de acceder a datos ( llamense RecordSet, mysql, postgres, etc.), y esto (como siempre) tocar lo menos posible el codigo.
vamos, querer que todo funcione igual, sin importar la forma en que estoy accediendo a los datos, lo que los "objetistas puros" llamam abstracion.
La forma que sugieres es crear una clase contenedora (como tambien lo ha explicado muy bien Antonio). Pero esto implicaria tener, en este caso, modificar (a mi parecer) mucho codigo. Te explico, por ejemplo se puede tener un metodo Create en TData, esto se utilizaria, por ejemplo para poder crear la tabla en momento de ejecucion, utilizamos la data 'cFileName', que es una classdata de las hijas, indica el nombre del archivo a crear ( 'CLIENTES', 'FACTURAS', 'RECIBOS'), por ejemplo podemos tener:.
Code: Select all
METHOD Create() CLASS TData CONSTRUCTOR
Super:Create( ::cFileName, ::Structure(), ::cDriver )
// ::Structure() es um metodo, que me devolvera la estructura que debe de tener la tabla, no confundir con ::DbStructure() que devueve la estrutura fisica existente.
Return Self
Utlizando la sugerencia tendriamos (ojo de el METHOD Create es Contructor), es decir aun no sabemos como estamos acceder a los datos.
Code: Select all
Method Create( nTipo ) class tData
local lRet := .f.
Do Case
case nTipo == TIPO_DATABASE
::oData := TDataBase():Create( ::cFileName, ::Structure(), ::cDriver )
exit
case nTipo == TIPO_MYSQL
::oData := TMySql():Create( ::cFileName, ::Structure(), ::cDriver )
exit
case nTipo == TIPO_RS
::oData := TRs():Create( ::cFileName, ::Structure(), ::cDriver )
exit
EnCase
return ??? ( ::oData o Self ver cual es lo mejor )
Asi, por estilo tendriamos que modificar unos metodos, y enviar o establecer el tipo de acceso de datos.
Pero definiendo en un inicio como se comportaria TData mediante esto:
Code: Select all
...
Do Case
Case cType == 'DATABASE' // cType seria una variable global
s_oClass := IIF(.F.,, HBClass():new( "TData" , iif( .T., { @TDataBase() }, { @HBObject() } ), @TData() ) ) ;
Case cType == 'RS'
s_oClass := IIF(.F.,, HBClass():new( "TData" , iif( .T., { @TRs() }, { @HBObject() } ), @TData() ) ) ;
Case cType == 'MYSQL'
s_oClass := IIF(.F.,, HBClass():new( "TData" , iif( .T., { @TMysql() }, { @HBObject() } ), @TData() ) ) ;
...
...
METHOD New(...) INLINE Super:New(...)
METHOD Create(...) INLINE Super:Create(...)
METHOD Seek(...) INLINE Super:Seek(...)
...
Creo que no se modificaria poco codigo. Es solo indicar el Super:[Method] y es esa clase la encaragaria de eso.
entonces se tendria esto de aqui:
Code: Select all
+---------+
| TData |
| Sets |
+---+-----+
|
+------------+-------+------+-------------+
| | | |
+----+----+ +---+-----+ +----+----+ +---------+
| TDatBase| | TRs | | TMYSql | | T... |
| | | | | | | |
+----+----+ +---+-----+ +----+----+ +---------+
| | | |
+------------+--------+-----+-------------+
|
+----+----+
| TData |
| |
+----+----+
|
+------------+--------+-----+-------------+
| | | |
+----+----+ +---+-----+ +----+----+ +---------+
| TCientes| |TFacturas| | TRecibos| | T... |
| | | | | | | |
+---------+ +---------+ +---------+ +---------+
Esto creo que esta bien si es que queremos utilizar un mismo modo de acceder a los datos, es decir se accede mediante Mysql y nada mas, y el manejo de los datos se hacen mediante cursores, etc., lo que tenga mysql..
Pero, que sucede si queremos acceder tanto como DataBase y como TMysql, por ejemplo, para poder utilizar los datos en forma local, es decir obtenemos los datos (mediante una consulta puede ser), y estos datos queremos tratarlos como una dbf comun..
Es este caso que tendriamos que utilizar un contenedor de datos, puede ser dentro de la TMysql un oData que se comporte como Dbf, o como um TOracle, si es que queremos trabajar como tal.
Uds. que opinan?
Gracias.