none
Tres preguntitas elementales sobre clases y objetos RRS feed

  • Pregunta

  • 1º Para inicializar un campo se debe agregar un parámetro al constructor.
       Si estoy haciendo un control de usuario, pero el control lo añado en tiempo de diseño cómo agrego el parámetro al constructor?
    --------------------
    2º Según yo en la primera forma de devolver el valor de UnaPropiedad, UnaFunción solo se ejecuta una vez en el momento de crear la instancia no importa las veces que recupere el valor de UnaPropiedad, mientras que en la segunda forma UnaFuncion se calcula cada vez que se recupera UnaPropiedad ¿es eso correcto?

    Class UnaClase
      Private UnCampo as integer = UnaFuncion(UnParamentro)

      ReadOnly Property UnaPropiedad As Integer
        Get
          Return UnCampo
        End Get
      End Property
    End Class

    Class UnaClase
      ReadOnly Property UnaPropiedad As Integer
        Get
          Return UnaFuncion(UnParametro)
        End Get
      End Property
    End Class

    --------------------
    3º Si declaro una clase y esa clase tiene varios métodos, todos miembros de la clase, como el archivo se comienza hacer muy grande quiero sacar algunos de esos métodos y ponerlos en un archivo aparte pero al sacarlos no dejarían de ser miembros de la clase?

       En otras palabras cómo hago para poner algunos de los métodos de una clase en otro archivo y que sigan siendo miembros de esa clase.



    • Editado James-2016 lunes, 2 de enero de 2017 4:10
    lunes, 2 de enero de 2017 4:07

Respuestas

  • "James-2016" preguntó:

    > 1º Para inicializar un campo se debe agregar un parámetro al constructor.

    No es necesario. Puedes inicializar los campos de tu clase desde el constructor predeterminado, el cual no dispone de ningún parámetro:

    Public Class MiControl
    
        Inherits UserControl
    
        Private unCampo As String
    
        Public Sub New()
    
            ' Inicializar el campo con algún valor por defecto
            unCampo = "¡Hola, Mundo!"
    
        End Sub
    
    End Class

    Ten en cuenta que eso mismo es lo que hace el compilador de Visual Basic (y de otros lenguajes .NET) cuando a la vez que declaras un campo le asignas un valor por defecto:

        ' Declaramos un campo y le asignamos un valor
        Private unCampo As String = "¡Hola, Mundo!

    Lo anterior generará el mismo código que aparece en la implementación de arriba de la clase MiControl.

    Pero si tu intención es permitir que ese campo se declare con algún otro valor en tiempo de ejecución, entonces necesitarás sobrecargar el constructor de la clase para obtener dicho valor:

    Public Class MiControl
    
        Inherits UserControl
    
        Private unCampo As String
    
        Public Sub New(nuevoValor As String)
            unCampo = nuevoValor
        End Sub
    
    End Class

    En éste caso, y al tratarse de un control de usuario (la clase hereda de UserControl), necesariamente tienes que implementar explícitamente el constructor por defecto (el procedimiento Sub New sin parámetros), siempre y cuando desees poder arrastrar tu control desde el Cuadro de herramientas hacia cualquier formulario de tu proyecto:

    Public Class MiControl
    
        Inherits UserControl
    
        Private unCampo As String
    
        Public Sub New()
    
            ' Constructor predeterminado. Inicializar el
            ' el campo con un valor por defecto:
            unCampo = "¡Hola, Mundo!"
    
        End Sub
    
        Public Sub New(nuevoValor As String)
    
            ' Constructor sobrecargado. Inicializar el
            ' el campo con el valor especificado:
            unCampo = nuevoValor
    
        End Sub
    
    End Class

    Te comento que si ese campo está declarado como de sólo lectura (ReadOnly), entonces el campo SOLAMENTE se podrá inicializar en algún constructor de la clase, siendo inalterable su valor desde cualquier otra parte diferente de la clase. Es decir, si en tu clase te limitas a declarar el siguiente campo:

        Private ReadOnly unCampo As String = "¡Hola, Mundo!"

    el compilador te generará el mismo código que aparece más arriba, con la salvedad que SOLAMENTE podrás modificar el valor del campo de sólo lectura desde algún constructor de la clase, sea el constructor predeterminado (Sub New()) o algún otro que tengas definido con parámetros.

    > 2º Según yo en la primera forma de devolver el valor de UnaPropiedad,
    > UnaFunción solo se ejecuta una vez en el momento de crear la instancia
    > no importa las veces que recupere el valor de UnaPropiedad, mientras
    > que en la segunda forma UnaFuncion se calcula cada vez que se recupera
    > UnaPropiedad ¿es eso correcto?

    No es correcto. UnaFuncion como el bloque Get de UnaPropiedad se ejecutarán tantas veces como sean invocadas. ¿Que la llamas una sola vez? Pues se ejecutará esa única vez. Pero si desde la propia clase, o desde las clases cliente, las llamas 20.000 veces, pues se ejecutarán otras tantas veces.

    Puede que te dé la sensación de que el bloque Get de un procedimiento Property solamente se ejecuta una vez, porque cuando recorres el código fuente Paso a paso (pulsando la tecla F8) no se entra en dicho bloque, y eso se debe a que seguramente tienes establecido el valor Saltar propiedades y operadores (solo administrado) en las Opciones de Visual Studio:

    Si desmarcas dicha opción, observarás que el código entrará en los bloques Get y Set de las propiedades (procedimientos Property), cosa que se hará SIEMPRE, esté o no marcada la opción comentada, porque en tiempo de ejecución no se recorre el código Paso a paso. ;-)

    > 3º Si declaro una clase y esa clase tiene varios métodos, todos miembros
    > de la clase, como el archivo se comienza hacer muy grande quiero sacar
    > algunos de esos métodos y ponerlos en un archivo aparte pero al sacarlos
    > no dejarían de ser miembros de la clase?

    ¡Que manía conque el archivo "se hace muy grande"! ¿Y eso es malo? Se nota que has visto pocas clases. ¡Lo mismo pretendes que nuestra clase haga todo el trabajo posible, y más, con sólo tres líneas de código! ;-)

    Creo que la pregunta se contesta por sí misma. Si tu sacas un método de la clase, ese método ya no pertenece a la clase MiControl o como se llame la clase; pertenecerá a otra clase diferente. ¿Dónde piensas meter los métodos que saques de la clase? Digo yo que será en otra clase.

    Si por casualidad tu respuesta es que dichos métodos deseas meterlos en un Module, te diré que ese Module se convierte en una Class no heredable (NotInheritable) cuando compiles tu proyecto, estando compartidos los métodos existentes en la misma, es decir, como si tuvieran definidos con la palabra Shared:

        Friend Module MiModulo
    
            Public Sub MiProcedimiento()
            End Sub
    
            Public Function MiFuncion() As Integer
            End Function
    
        End Module

    Cuando compiles el proyecto, el compilador lo cambiará por lo siguiente:

        <StandardModule> _
        Friend NotInheritable Class MiModulo
        
            Public Shared Function MiFuncion() As Integer
            End Function
    
            Public Shared Sub MiProcedimiento()
            End Sub
    
        End Class

    Así que piensa que un Module no es más que otra Class con métodos compartidos. ;-)

    > En otras palabras cómo hago para poner algunos de los métodos de una
    > clase en otro archivo y que sigan siendo miembros de esa clase.

    Para responder a esa pregunta, habría que redefinir el concepto de clase en el mundo de la Programación Orientada a Objetos:

    Programación orientada a objetos en Visual Basic

    Si esos métodos que dices que deseas sacar de la clase son métodos auxiliares que lo mismo de bien trabajan con una clase Cliente como con una clase Proveedor, lo que tienes que hacer es incluir esos métodos en una clase aparte con métodos compartidos (como si los métodos los incluyeras en un Module), para que puedan ser utilizados desde otras clases diferentes. Pero está claro que esos métodos ya no pertenecerán a la clase X, Y o Z; pertenecerán a la clase dónde se encuentren declarados. ;-)


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.



    lunes, 2 de enero de 2017 6:46
    Moderador
  • "James-2016" escribió:

    > Sí, exacto, eso es precisamente lo que trato de hacer, solo que la consulta
    > es la siguiente, por ejemplo si creo una instancia en la que quiero
    > inicializar un campo, la crearía así:
    >
    > Dim NuevoObjeto as New LaClase(Valor)
    >
    > Y allí, en Valor, estaría pasándole al constructor el valor del parámetro que
    > quiero inicializar, ...

    Efectivamente, así es.

    > ... lo que trato de saber es cómo le paso ese valor si la clase es un control
    > de usuario que ya lo agregué en el diseñador del formulario.
    >

    Si en el editor de Visual Studio ya has "soltado" el control sobre el formulario, EN TIEMPO DE DISEÑO, lo que tú pretendes hacer NO ES POSIBLE, de hecho, anteriormente te he comentado lo siguiente:

        [...] En éste caso, y al tratarse de un control de usuario (la clase hereda de UserControl),
        necesariamente tienes que implementar explícitamente el constructor por defecto (el
        procedimiento Sub New sin parámetros), siempre y cuando desees poder arrastrar tu control
        desde el Cuadro de herramientas hacia cualquier formulario de tu proyecto[...]

    > En otras palabras, al haberlo agregado al formulario ya cree la instancia,
    > pero, en ese caso ¿cómo le "echo" el Valor del parámetro?

    Pues muy fácil, a través del bloque Set de la correspondiente propiedad a la que pertenece el campo en cuestión. ¿Cómo crees que se le asigna las propiedades a los controles TextBox, Button, ComboBox, DataGridView, etc., que ya existen en el formulario? Pues a través de la Ventana de Propiedades, que a su vez escribe los valores nuevos en el procedimiento InitializeComponente que todo formulario que se haya creado con Visual Studio dispone.

    Si tu control dispone de un campo privado y deseas que desde fuera de su clase se le asigne un valor que no sea mediante un constructor con parámetros, necesariamente tendrás que disponer de un procedimiento Property de lectura (Get) y escritura (Set). Obviamente, en éste caso, ese campo privado no puede ser de sólo lectura (ReadOnly), porque como también te he comentado anteriormente, el valor de un campo de sólo lectura solamente puede ser asignado en algún constructor de la clase a la que pertenece.

    > En la declaración de abajo, observe que UnCampo se inicializa en la
    > primera línea y en el cuerpo Get de la porpiedad se retorna UnCampo
    > (asignado previamente), en ese caso, cuando hago esto:
    >
    > ValorDelCampo = MiObjeto.UnaPropiedad
    >
    > ¿al invocar a UnaPropiedad como en la línea de arriba igual se ejecuta
    > UnaFuncion pese a que está en la primera línea de la clase? ¿No se ejecuta
    > y asigna a UnCampo solo en el momento de crear la instancia?

    ¡Hombre! En esta caso, a la función UnaFuncion solamente se la llamará una vez, en el constructor sin parámetros, y el bloque Get de la propiedad UnaPropiedad se limitará a devolver el valor del campo:

        Public NotInheritable Class MiControl
    
            Inherits UserControl
    
            Private unCampo As String
        
            Public Sub New()
                Me.unCampo = Me.UnaFuncion(3)
            End Sub
    
            ReadOnly Property UnaPropiedad As Integer
                Get
                   Return UnCampo
                End Get
            End Property
    
        End Class
    

    > Entonces ¿lo de arriba es exactamente igual a lo de abajo?
    >
    >   ReadOnly Property UnaPropiedad As Integer
    >       Get
    >           Return UnaFuncion(UnParametro)
    >       End Get
    >   End Property

    No es igual, porque si llamas a la función desde el propio bloque Get, cada vez que desees recuperar el valor de la propiedad se tendrá que ejecutar la función.

    > Por último, de ser afirmativas las respuestas, ...

    Como no son afirmativas ambas respuestas, me ahorro de responder. :-))

    > Respecto a la tercera consulta, por lo que me dice, me parece entonces,
    > que en este caso es más conveniente dejar sus métodos en el mismo
    > archivo para que sigan perteneciendo a esa clase.

    Si tu deseas que esos métodos pertenezcan a esa clase, tendrás que dejarlos ahí. ;-)


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    • Marcado como respuesta James-2016 lunes, 2 de enero de 2017 12:35
    lunes, 2 de enero de 2017 12:03
    Moderador
  • "James-2016" escribió:

    > entonces en ese caso tendría que crear una propiedad de solo escritura
    > para inicializar el valor, ya no le pasaría el parámetro al constructor
    > sino que se crearía con el constructor por defecto.

    Tú puedes inicializar el valor del campo en algún constructor de la clase para, digamos, asignarle un valor por defecto. ¿OK?

    Pero, si POSTERIORMENTE, en el transcurso normal de ejecución de la aplicación, deseas cambiarle de color, asignarle un texto, cambiar su fuente, en definitiva, MODIFICAR el valor que por defecto tiene ese campo, necesitarás tener una propiedad de LECTURA/ESCRITURA, para que la misma devuelva el valor del campo (Get) y se le pueda modificar su valor (Set):

        Private unCampo As Integer
    
        Public Property Campo As Integer
            Get
                ' Devolver el valor del campo
                Return unCampo
            End Get
            Set(value As Integer)
                ' Establecer el valor del campo
                unCampo = value
            End Set
        End Property

    Obivamente, si la propiedad es de escritura, no puede ser de sólo lectura (ReadOnly).

    > Recapitulando, habría que crear una propiead para inicializar el valor.

    No es necesario si a la hora de declarar el campo le has asignado un valor por defecto. Pero si ese campo es modificable, tendrás que habilitar una propiedad con un bloque Set, tal y como te he indicado anteriormente, para que se le pueda asignar el NUEVO VALOR al campo.


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.


    lunes, 2 de enero de 2017 12:55
    Moderador
  • James-2016,

    Respecto a la tercera pregunta:

    {?}- Si declaro una clase y esa clase tiene varios métodos, todos miembros de la clase, como el archivo se comienza hacer muy grande quiero sacar algunos de esos métodos y ponerlos en un archivo aparte pero al sacarlos no dejarían de ser miembros de la clase?

    ¿Cuántos son varios métodos para ti?. Si la clase define correctamente los métodos necesarios (entendiendo los principios de responsabilidad única) entonces todos los miembros que necesites escribir serán los necesarios para cumplir con la definición de la clase, claro, cuidando de no convertir la misma en "multi-propósito" (algo así como una navaja suiza). Toma en cuenta también los principios de reutilización (DRY), escribir código legible y de fácil mantenimiento (KISS) entre otros principios de diseño o algunas métricas como la complejidad ciclomática que tiene que ver con cuan complejo es tu código en términos cuantitativos; como vez no sólo es escribir código, sino saber como escribir, no sólo es buscar tener menos líneas de código sino saber como y cuando hacerlo.

    Retomando el tema de la tercera pregunta, existen otros criterios para decidir "partir" una clase en más de un archivo, por ejemplo cuando mas de un desarrollador debe trabaja sobre una misma clase de manera concurrente o para "separar" el código generado por alguna herramienta de los cambios realizados por el desarrollador (bastante común cuando se usa el enfoque DataBaseFirst de Entity Framework), etc.; bajo cualquier otra "excusa" es posible separar la definición de una clase en más de un archivo, el compilador será el encargado de tomar todas las partes y fusionarlas en una sola y ello lo consigues de manera simple definiendo una clase como parcial

    'Archivo1
    Partial Public Class Empleado  
        Public Sub CalcularHorasRegulares()  
        End Sub  
    End Class  
      
    'Archivo2
    Partial Public Class Empleado
        Public Sub CalcularHorasExtras()  
        End Sub  
    End Class  
    

    Para mayor información te dejo el enlace Partial (Visual Basic)


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    lunes, 2 de enero de 2017 15:16

Todas las respuestas

  • "James-2016" preguntó:

    > 1º Para inicializar un campo se debe agregar un parámetro al constructor.

    No es necesario. Puedes inicializar los campos de tu clase desde el constructor predeterminado, el cual no dispone de ningún parámetro:

    Public Class MiControl
    
        Inherits UserControl
    
        Private unCampo As String
    
        Public Sub New()
    
            ' Inicializar el campo con algún valor por defecto
            unCampo = "¡Hola, Mundo!"
    
        End Sub
    
    End Class

    Ten en cuenta que eso mismo es lo que hace el compilador de Visual Basic (y de otros lenguajes .NET) cuando a la vez que declaras un campo le asignas un valor por defecto:

        ' Declaramos un campo y le asignamos un valor
        Private unCampo As String = "¡Hola, Mundo!

    Lo anterior generará el mismo código que aparece en la implementación de arriba de la clase MiControl.

    Pero si tu intención es permitir que ese campo se declare con algún otro valor en tiempo de ejecución, entonces necesitarás sobrecargar el constructor de la clase para obtener dicho valor:

    Public Class MiControl
    
        Inherits UserControl
    
        Private unCampo As String
    
        Public Sub New(nuevoValor As String)
            unCampo = nuevoValor
        End Sub
    
    End Class

    En éste caso, y al tratarse de un control de usuario (la clase hereda de UserControl), necesariamente tienes que implementar explícitamente el constructor por defecto (el procedimiento Sub New sin parámetros), siempre y cuando desees poder arrastrar tu control desde el Cuadro de herramientas hacia cualquier formulario de tu proyecto:

    Public Class MiControl
    
        Inherits UserControl
    
        Private unCampo As String
    
        Public Sub New()
    
            ' Constructor predeterminado. Inicializar el
            ' el campo con un valor por defecto:
            unCampo = "¡Hola, Mundo!"
    
        End Sub
    
        Public Sub New(nuevoValor As String)
    
            ' Constructor sobrecargado. Inicializar el
            ' el campo con el valor especificado:
            unCampo = nuevoValor
    
        End Sub
    
    End Class

    Te comento que si ese campo está declarado como de sólo lectura (ReadOnly), entonces el campo SOLAMENTE se podrá inicializar en algún constructor de la clase, siendo inalterable su valor desde cualquier otra parte diferente de la clase. Es decir, si en tu clase te limitas a declarar el siguiente campo:

        Private ReadOnly unCampo As String = "¡Hola, Mundo!"

    el compilador te generará el mismo código que aparece más arriba, con la salvedad que SOLAMENTE podrás modificar el valor del campo de sólo lectura desde algún constructor de la clase, sea el constructor predeterminado (Sub New()) o algún otro que tengas definido con parámetros.

    > 2º Según yo en la primera forma de devolver el valor de UnaPropiedad,
    > UnaFunción solo se ejecuta una vez en el momento de crear la instancia
    > no importa las veces que recupere el valor de UnaPropiedad, mientras
    > que en la segunda forma UnaFuncion se calcula cada vez que se recupera
    > UnaPropiedad ¿es eso correcto?

    No es correcto. UnaFuncion como el bloque Get de UnaPropiedad se ejecutarán tantas veces como sean invocadas. ¿Que la llamas una sola vez? Pues se ejecutará esa única vez. Pero si desde la propia clase, o desde las clases cliente, las llamas 20.000 veces, pues se ejecutarán otras tantas veces.

    Puede que te dé la sensación de que el bloque Get de un procedimiento Property solamente se ejecuta una vez, porque cuando recorres el código fuente Paso a paso (pulsando la tecla F8) no se entra en dicho bloque, y eso se debe a que seguramente tienes establecido el valor Saltar propiedades y operadores (solo administrado) en las Opciones de Visual Studio:

    Si desmarcas dicha opción, observarás que el código entrará en los bloques Get y Set de las propiedades (procedimientos Property), cosa que se hará SIEMPRE, esté o no marcada la opción comentada, porque en tiempo de ejecución no se recorre el código Paso a paso. ;-)

    > 3º Si declaro una clase y esa clase tiene varios métodos, todos miembros
    > de la clase, como el archivo se comienza hacer muy grande quiero sacar
    > algunos de esos métodos y ponerlos en un archivo aparte pero al sacarlos
    > no dejarían de ser miembros de la clase?

    ¡Que manía conque el archivo "se hace muy grande"! ¿Y eso es malo? Se nota que has visto pocas clases. ¡Lo mismo pretendes que nuestra clase haga todo el trabajo posible, y más, con sólo tres líneas de código! ;-)

    Creo que la pregunta se contesta por sí misma. Si tu sacas un método de la clase, ese método ya no pertenece a la clase MiControl o como se llame la clase; pertenecerá a otra clase diferente. ¿Dónde piensas meter los métodos que saques de la clase? Digo yo que será en otra clase.

    Si por casualidad tu respuesta es que dichos métodos deseas meterlos en un Module, te diré que ese Module se convierte en una Class no heredable (NotInheritable) cuando compiles tu proyecto, estando compartidos los métodos existentes en la misma, es decir, como si tuvieran definidos con la palabra Shared:

        Friend Module MiModulo
    
            Public Sub MiProcedimiento()
            End Sub
    
            Public Function MiFuncion() As Integer
            End Function
    
        End Module

    Cuando compiles el proyecto, el compilador lo cambiará por lo siguiente:

        <StandardModule> _
        Friend NotInheritable Class MiModulo
        
            Public Shared Function MiFuncion() As Integer
            End Function
    
            Public Shared Sub MiProcedimiento()
            End Sub
    
        End Class

    Así que piensa que un Module no es más que otra Class con métodos compartidos. ;-)

    > En otras palabras cómo hago para poner algunos de los métodos de una
    > clase en otro archivo y que sigan siendo miembros de esa clase.

    Para responder a esa pregunta, habría que redefinir el concepto de clase en el mundo de la Programación Orientada a Objetos:

    Programación orientada a objetos en Visual Basic

    Si esos métodos que dices que deseas sacar de la clase son métodos auxiliares que lo mismo de bien trabajan con una clase Cliente como con una clase Proveedor, lo que tienes que hacer es incluir esos métodos en una clase aparte con métodos compartidos (como si los métodos los incluyeras en un Module), para que puedan ser utilizados desde otras clases diferentes. Pero está claro que esos métodos ya no pertenecerán a la clase X, Y o Z; pertenecerán a la clase dónde se encuentren declarados. ;-)


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.



    lunes, 2 de enero de 2017 6:46
    Moderador
  • Buenas, creo que no se entendió del todo la primera consulta (o no estoy entendiendo su respuesta jeje), me dice:

    "Pero si tu intención es permitir que ese campo se declare con algún otro valor en tiempo de ejecución, entonces necesitarás sobrecargar el constructor de la clase para obtener dicho valor"

    Sí, exacto, eso es precisamente lo que trato de hacer, solo que la consulta es la siguiente, por ejemplo si creo una instancia en la que quiero inicializar un campo, la crearía así:

    Dim NuevoObjeto as New LaClase(Valor)

    Y allí, en Valor, estaría pasándole al constructor el valor del parámetro que quiero inicializar, lo que trato de saber es cómo le paso ese valor si la clase es un control de usuario que ya lo agregué en el diseñador del formulario.

    En otras palabras, al haberlo agregado al formulario ya cree la instancia, pero, en ese caso ¿cómo le "echo" el Valor del parámetro?

    ----------------------------------------------------------------------------------------------------------

    En cuanto a la segunda consulta vuelvo a la carga sólo para estar completamente seguro:

    En la declaración de abajo, observe que UnCampo se inicializa en la primera línea y en el cuerpo Get de la porpiedad se retorna UnCampo (asignado previamente), en ese caso, cuando hago esto:

    ValorDelCampo = MiObjeto.UnaPropiedad

    ¿al invocar a UnaPropiedad como en la línea de arriba igual se ejecuta UnaFuncion pese a que está en la primera línea de la clase? ¿No se ejecuta y asigna a UnCampo solo en el momento de crear la instancia?

    Class UnaClase
      Private UnCampo as integer = UnaFuncion(UnParamentro)

      ReadOnly Property UnaPropiedad As Integer
        Get
          Return UnCampo
        End Get
      End Property
    End Class

    ------------------------------------------------------------------------------------------------------

    Entonces ¿lo de arriba es exactamente igual a lo de abajo? ¿en ambos casos UnaFuncion se ejecutará sí o sí cada vez que recupere el valor de la propiedad? (obsérvese que en el código de abajo UnaFunción sí la invoco desde el cuerpo Get)

    Class UnaClase
      ReadOnly Property UnaPropiedad As Integer
        Get
          Return UnaFuncion(UnParametro)
        End Get
      End Property
    End Class

    ------------------------------------------

    Por último, de ser afirmativas las respuestas, se da el caso (para lo que trato de hacer) que el valor de la propiedad lo calculo en base a una función pero ese valor calculado de esa propiedad en particular no cambia nunca durante la existencia del objeto, entonces encuentro que sería ineficiente que cada vez quiera leer el valor de la propiedad, se ejecute la función, porque como no cambia de valor no tendría sentido que se recalcule una y otra vez y entonces, en ese caso particular, ¿cuál sería la manera más eficiente de hacerlo?

    ----------------------------------------------------------------------------------------------------------

    Respecto a la tercera consulta, por lo que me dice, me parece entonces, que en este caso es más conveniente dejar sus métodos en el mismo archivo para que sigan perteneciendo a esa clase.

    Gracias por la respuesta.


    • Editado James-2016 lunes, 2 de enero de 2017 11:10
    lunes, 2 de enero de 2017 11:09
  • "James-2016" escribió:

    > Sí, exacto, eso es precisamente lo que trato de hacer, solo que la consulta
    > es la siguiente, por ejemplo si creo una instancia en la que quiero
    > inicializar un campo, la crearía así:
    >
    > Dim NuevoObjeto as New LaClase(Valor)
    >
    > Y allí, en Valor, estaría pasándole al constructor el valor del parámetro que
    > quiero inicializar, ...

    Efectivamente, así es.

    > ... lo que trato de saber es cómo le paso ese valor si la clase es un control
    > de usuario que ya lo agregué en el diseñador del formulario.
    >

    Si en el editor de Visual Studio ya has "soltado" el control sobre el formulario, EN TIEMPO DE DISEÑO, lo que tú pretendes hacer NO ES POSIBLE, de hecho, anteriormente te he comentado lo siguiente:

        [...] En éste caso, y al tratarse de un control de usuario (la clase hereda de UserControl),
        necesariamente tienes que implementar explícitamente el constructor por defecto (el
        procedimiento Sub New sin parámetros), siempre y cuando desees poder arrastrar tu control
        desde el Cuadro de herramientas hacia cualquier formulario de tu proyecto[...]

    > En otras palabras, al haberlo agregado al formulario ya cree la instancia,
    > pero, en ese caso ¿cómo le "echo" el Valor del parámetro?

    Pues muy fácil, a través del bloque Set de la correspondiente propiedad a la que pertenece el campo en cuestión. ¿Cómo crees que se le asigna las propiedades a los controles TextBox, Button, ComboBox, DataGridView, etc., que ya existen en el formulario? Pues a través de la Ventana de Propiedades, que a su vez escribe los valores nuevos en el procedimiento InitializeComponente que todo formulario que se haya creado con Visual Studio dispone.

    Si tu control dispone de un campo privado y deseas que desde fuera de su clase se le asigne un valor que no sea mediante un constructor con parámetros, necesariamente tendrás que disponer de un procedimiento Property de lectura (Get) y escritura (Set). Obviamente, en éste caso, ese campo privado no puede ser de sólo lectura (ReadOnly), porque como también te he comentado anteriormente, el valor de un campo de sólo lectura solamente puede ser asignado en algún constructor de la clase a la que pertenece.

    > En la declaración de abajo, observe que UnCampo se inicializa en la
    > primera línea y en el cuerpo Get de la porpiedad se retorna UnCampo
    > (asignado previamente), en ese caso, cuando hago esto:
    >
    > ValorDelCampo = MiObjeto.UnaPropiedad
    >
    > ¿al invocar a UnaPropiedad como en la línea de arriba igual se ejecuta
    > UnaFuncion pese a que está en la primera línea de la clase? ¿No se ejecuta
    > y asigna a UnCampo solo en el momento de crear la instancia?

    ¡Hombre! En esta caso, a la función UnaFuncion solamente se la llamará una vez, en el constructor sin parámetros, y el bloque Get de la propiedad UnaPropiedad se limitará a devolver el valor del campo:

        Public NotInheritable Class MiControl
    
            Inherits UserControl
    
            Private unCampo As String
        
            Public Sub New()
                Me.unCampo = Me.UnaFuncion(3)
            End Sub
    
            ReadOnly Property UnaPropiedad As Integer
                Get
                   Return UnCampo
                End Get
            End Property
    
        End Class
    

    > Entonces ¿lo de arriba es exactamente igual a lo de abajo?
    >
    >   ReadOnly Property UnaPropiedad As Integer
    >       Get
    >           Return UnaFuncion(UnParametro)
    >       End Get
    >   End Property

    No es igual, porque si llamas a la función desde el propio bloque Get, cada vez que desees recuperar el valor de la propiedad se tendrá que ejecutar la función.

    > Por último, de ser afirmativas las respuestas, ...

    Como no son afirmativas ambas respuestas, me ahorro de responder. :-))

    > Respecto a la tercera consulta, por lo que me dice, me parece entonces,
    > que en este caso es más conveniente dejar sus métodos en el mismo
    > archivo para que sigan perteneciendo a esa clase.

    Si tu deseas que esos métodos pertenezcan a esa clase, tendrás que dejarlos ahí. ;-)


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    • Marcado como respuesta James-2016 lunes, 2 de enero de 2017 12:35
    lunes, 2 de enero de 2017 12:03
    Moderador
  • ¡Ah! ok, entonces en ese caso tendría que crear una propiedad de solo escritura para inicializar el valor, ya no le pasaría el parámetro al constructor sino que se crearía con el constructor por defecto.

    Recapitulando, habría que crear una propiead para inicializar el valor. De la declaración de las propiedades, la primera forma sería más eficiente para el caso, y, para que los métodos sean miembros de la clase necesariamente debo conservarlos en el mismo archivo.

    Muchas gracias, me quedaron más claras las cosas.

    lunes, 2 de enero de 2017 12:30
  • "James-2016" escribió:

    > entonces en ese caso tendría que crear una propiedad de solo escritura
    > para inicializar el valor, ya no le pasaría el parámetro al constructor
    > sino que se crearía con el constructor por defecto.

    Tú puedes inicializar el valor del campo en algún constructor de la clase para, digamos, asignarle un valor por defecto. ¿OK?

    Pero, si POSTERIORMENTE, en el transcurso normal de ejecución de la aplicación, deseas cambiarle de color, asignarle un texto, cambiar su fuente, en definitiva, MODIFICAR el valor que por defecto tiene ese campo, necesitarás tener una propiedad de LECTURA/ESCRITURA, para que la misma devuelva el valor del campo (Get) y se le pueda modificar su valor (Set):

        Private unCampo As Integer
    
        Public Property Campo As Integer
            Get
                ' Devolver el valor del campo
                Return unCampo
            End Get
            Set(value As Integer)
                ' Establecer el valor del campo
                unCampo = value
            End Set
        End Property

    Obivamente, si la propiedad es de escritura, no puede ser de sólo lectura (ReadOnly).

    > Recapitulando, habría que crear una propiead para inicializar el valor.

    No es necesario si a la hora de declarar el campo le has asignado un valor por defecto. Pero si ese campo es modificable, tendrás que habilitar una propiedad con un bloque Set, tal y como te he indicado anteriormente, para que se le pueda asignar el NUEVO VALOR al campo.


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.


    lunes, 2 de enero de 2017 12:55
    Moderador
  • Ok, gracias.
    lunes, 2 de enero de 2017 13:12
  • James-2016,

    Respecto a la tercera pregunta:

    {?}- Si declaro una clase y esa clase tiene varios métodos, todos miembros de la clase, como el archivo se comienza hacer muy grande quiero sacar algunos de esos métodos y ponerlos en un archivo aparte pero al sacarlos no dejarían de ser miembros de la clase?

    ¿Cuántos son varios métodos para ti?. Si la clase define correctamente los métodos necesarios (entendiendo los principios de responsabilidad única) entonces todos los miembros que necesites escribir serán los necesarios para cumplir con la definición de la clase, claro, cuidando de no convertir la misma en "multi-propósito" (algo así como una navaja suiza). Toma en cuenta también los principios de reutilización (DRY), escribir código legible y de fácil mantenimiento (KISS) entre otros principios de diseño o algunas métricas como la complejidad ciclomática que tiene que ver con cuan complejo es tu código en términos cuantitativos; como vez no sólo es escribir código, sino saber como escribir, no sólo es buscar tener menos líneas de código sino saber como y cuando hacerlo.

    Retomando el tema de la tercera pregunta, existen otros criterios para decidir "partir" una clase en más de un archivo, por ejemplo cuando mas de un desarrollador debe trabaja sobre una misma clase de manera concurrente o para "separar" el código generado por alguna herramienta de los cambios realizados por el desarrollador (bastante común cuando se usa el enfoque DataBaseFirst de Entity Framework), etc.; bajo cualquier otra "excusa" es posible separar la definición de una clase en más de un archivo, el compilador será el encargado de tomar todas las partes y fusionarlas en una sola y ello lo consigues de manera simple definiendo una clase como parcial

    'Archivo1
    Partial Public Class Empleado  
        Public Sub CalcularHorasRegulares()  
        End Sub  
    End Class  
      
    'Archivo2
    Partial Public Class Empleado
        Public Sub CalcularHorasExtras()  
        End Sub  
    End Class  
    

    Para mayor información te dejo el enlace Partial (Visual Basic)


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    lunes, 2 de enero de 2017 15:16
  • A tener muy en cuenta el comentario, muy interesante, gracias por la respuesta tendré todo lo dicho muy presente respecto a los principios a observar siempre. Gracias.

    mm algo así como una clase debe hacer lo que debe hacer y ni una cosa más.

    No es que sea tan grande tampoco, son alrededor de 350 líneas, la declaración de clase parcial, sería entonces una alternativa también, pero por lo dicho en ambas respuestas, creo que mejor lo mantengo todo en un solo archivo.

    lunes, 2 de enero de 2017 19:06