![]() |
problemas la hacer un cast de un TStringGrid(DBGrid)
Hola, tengo una procediminto <procedure stringGridFill(grid:TStringGrid)> que anda bien para StringGrid este solo hace que las columnas se auto-ajusten dependiendo del largo de los string que muestra.
Quiero usar la misma funcion para una DBgrid, por ejemplo: DBGrid1.DataSource.DataSet.DisableControls; TStringGrid(DBGrid1).DefaultRowHeight:=60; DBGrid1.DataSource.DataSet.EnableControls; este codigo anda, entonces lo que yo hago es: DBGrid1.DataSource.DataSet.DisableControls; stringGridFill(TStringGrid(DBGrid1)) (x) DBGrid1.DataSource.DataSet.EnableControls; pero en la linea (x) salta un error de direccionamiento, y no es dentro del procedure, ya que es antes de llegar al begin de stringGridFill, por eso me da a penzar que hay algo mal, en el cast.. que es? |
que error te da? Porque lo acabo de probar y me funciona sin problemas
|
Hola:
Por lo que cuentas, tiene toda la pinta de que el método al que llamas pertenece sólo a la clase TStringGrid y no al ascendiente común TCustomGrid. El compilador te deja pasar la sentencia, pero falla en la ejecución. Con DefaultRowHeight eso no ocurría porque sí es común a ambas clases, auqneu esté protegido para una y public para la otra. Revisa el código de la VCL, a ver si el TCustomGrid tiene implementado dicho método. Un saludo |
Orfeo:
Esto, TStringGrid(DBGrid1).DefaultRowHeight:=60; *jamás* debe hacerse. TDBGrid y TStringGrid no están en la misma línea de la jerarquía de clases. En general cuando haces el "casting" TUnaClase(Objeto) Objeto debe ser de una clase ancestra de TUnaClase como en Código:
var // Saludos |
Hola:
Roman escribió: Cita:
Quizás una forma más ortodoxa sería heredar un componente de TDBGrid y promover dicha propiedad a la sección public, o en caso de un método virtual, redefinirlo como public, pero es un trabajo extra que podemos evitar. Por supuesto, este truco está supeditado a conocer de antemano la declaración de las clases que estamos manejando (para eso está el código fuente), pero eso sucede con el uso diario de componentes, su implementación puede variar de una versión a otra, y de hecho sucede, pero esa es una información de la que dispone el programador. Ya ves, Roman, siempre dispuesto a replicarte. Espero tu contraréplica. Un slaudo |
Cita:
TDBGrid -> TCustomDBGrid -> TCustomGrid TStringGrid -> TDrawGrid -> TCustomGrid |
Andrés, me parece que nos estamos confundiendo. Si una clase ancestra dispone de un método protegido entonces desde luego que es válido hacer el casting usando la clase ancestra. Pero en este caso, como ya lo mostró delphi.com.ar, las clases en cuestión no están en la misma línea jerárquica. Es como hacer que un primo mío se haga pasar por mí. Esto, si bien puede funcionar en algunos casos porque el primo por casualidad tenga un método del mismo nombre, puede llevar a problemas de violación de acceso.
Sí, quizá en algún momento nos ahorre trabajo, pero cuando nos acostumbremos a este tipo de trucos y la aplicación comience a fallar nos costará más trabajo hallar la causa. // Saludos |
Hola:
Delphi.com.ar escribió: Cita:
Cuando hacemos el cast TStringGrid(DBGrid1) simplemente engañamos al compilador para que no proteste pero la instrucción/propiedad que se ejecuta es la del ancestro (probadlo si queréis), la del TCustomGrid, no la del TStringGrid (eso si podría ser una fuente de complicaciones). De esa forma accedemos a una propiedad que pertenece plenamente a nuestra clase. Roman escribió: Cita:
Saludos |
Cita:
Para hacer esto es conveniente crear una clase intermedia, heredada de TDBGrid, que ya posea esta propiedad, por ejemplo: TMyDbGrid = class(TDBGrid) public property DefaultRowHeight; end; Y si quieres puedes castear a esta clase tu grid sin problemas. Saludos! |
Ok Andrés, aquí te va un pequeño relato
El señor Bor Land definió tres clases: Código:
TGrid = class Código:
function TStringGrid.GetRowHeight: Integer; La documentación nada dice acerca de Font pues es una propiedad privada que no interesa al público en general. Como DbGrid es una instancia de TDbGrid no posee el campo Font, así que ¿qué sucederá cuando nuestro protagonista escriba: TStringGrid(DbGrid).RowHeight := 60; ? ¡¡Una violación de acceso!! Y colorín colorado, este cuento se ha acabado // Saludos |
Hola foreros:
¡ Me habéis convencido en un 99 %! El ejemplo de Roman, aunque sea un cuento y no se corresponda con la implementación de DefaultRowHeight en la VCL (Bor Land debe ser un primo de Borland), ilustra que este truco puede ser una fuente potencial de errores al redefinirse el método Set de la propiedad, por mucho que la propiedad sea común a todos. En las pruebas que he hecho, Delphi toma el primer camino conocido, si la propiedad sólo se ha promovido de sección, se ejecuta el código del ancestro y no saltan errores; en cambio, si la propiedad se promueve de sección y además se accede desde un método no común (como el ejemplo de Roman), ya se entra en un terreno sembrado de minas, puesto que se ejecuta el código de la clase que utilizamos para "castear". Si fuera un método virtual, "a secas", y se redefiniera no ocurriría nada malo porque se ejecutaría el método del ancestro (el casting, aunque ilegal según la OOP, tendría un efecto de polimorfismo real). Si fuera un método virtual y abstracto a la vez (lo lógico sería que sí estuviera redefinido en la clase que lo publica), al hacer el casting se ejecutaría igualmente el código del ancestro, saltando un "Abstract error", pero esto ya es afinar demasiado. Hasta ahora me había parecido un truco válido y fiable, aunque la teoría OOP diga que no se debe moldear salvo a un ascendente, creía que no había peligro al ejecutarse el código ancestral. Sopesando ahora sus pros y sus contras, os doy la razón en que no es un truco recomendable. Como señala Delphi.Com.Ar, lo mejor es derivar una clase. Si alguien pregunta, ¿y cuál es el 1% que no te convence? Pues que con TStringGrid(DBGrid1).DefaultRowHeight = 60; logramos el efecto deseado sin errores y sin mucho código, aunque no se atenga a la ortodoxia. Gracias por vuestras explicaciones. Saludos PD: ... y fueron felices y comieron perdices |
:D :D Voy contra el 1% :D :D
Cita:
Epílogo: El lobo se come a caperucita :D // Saludos pd: Andrés, esto último es nada más para bromear un poquillo. Siempre es grato contender contigo ya que de los debates en buenos términos siempre se aprenden cosas nuevas. |
En realidad, todos tenian razon con lo del cast, el problema es que en mi codigo en un momento dado, accede a cols[i] y este no esta definido en en algun ancestro de DBgrid, parece que solo se define en stringGrid (aunque no me fije).
Ahora el problema es que nesecito acceder a un DBGrid como si fuese una matriz, osea col[i,j], por eso voy a postear otro mensaje en el foro. Gracias |
La franja horaria es GMT +2. Ahora son las 03:52:55. |
Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi