2.1 DECLARACIÓN DE CLASES: ATRIBUTOS, MÉTODOS, ENCAPSULAMIENTO. OBJETOS Un objeto es una agrupación de código, compuesta de propiedades (atributos) y métodos, que pueden ser manipulados como una entidad independiente. Las propiedades definen los datos o información del objeto, permitiendo consultar o modificar su estado. Los métodos son rutinas que definen su comportamiento. Un objeto desempeña un trabajo concreto dentro de una estructura organizativa de nivel superior, formada por múltiples objetos, cada uno de los cuales ejerce una tarea particular para la cual ha sido diseñado. Objeto “Empleado” CLASES Conjunto de especificaciones o normas que definen cómo va a ser creado un objeto de un tipo determinado. Plantilla de instrucciones que contiene las indicaciones para crear y manejar un objeto. INSTANCIAS DE UNA CLASE CARACTERÍSTICAS BÁSICAS DE UN SOO Abstracción Identificación de objetos a través de sus aspectos conceptuales. {Porsche 911, Opel Astra, Seat 600} є Coche Encapsulación Separación entre el interfaz del objeto y su implementación. Ventajas: Seguridad: evita accesos no deseados.
Simplicidad: no es necesario conocer la implementación
de un objeto para poder utilizarlo. Empleado.Alta(id) CARACTERÍSTICAS BÁSICAS DE UN SOO Polimorfismo Varios métodos con el mismo nombre pueden realizar acciones diferentes. Venado.Comer() Leon.Comer() Herencia Partiendo de una clase (base, padre o superclase) creamos una nueva (derivada, hija o subclase). La clase hija posee TODO el código de la clase padre, más el código propio que se quiera añadir. La clase derivada puede ser, a la vez, base. Simple (.NET) / Múltiple CARACTERÍSTICAS BÁSICAS DE UN SOO Polimorfismo Varios métodos con el mismo nombre pueden realizar acciones diferentes. Venado.Comer() Leon.Comer() Herencia Partiendo de una clase (base, padre o superclase) creamos una nueva (derivada, hija o subclase). La clase hija posee TODO el código de la clase padre, más el código propio que se quiera añadir. La clase derivada puede ser, a la vez, base. Simple (.NET) / Múltiple
Coche (Motor, Ruedas, Volante, Acelerar…)
CocheDeportivo (… + ABS, Turbo…) JERARQUÍAS DE CLASES CREACIÓN DE CLASES CREACIÓN DE ATRIBUTOS DE UNA CLASE CREACIÓN DE PROPIEDADES DE UNA CLASE ENCAPSULACIÓN El código de una clase debe permanecer protegido de modificaciones no controladas del exterior. Caja negra que expone una interfaz para su uso. ENCAPSULACIÓN A TRAVÉS DE PROPIEDADES Module General Sub Main() Dim loEmpleado As Empleado loEmpleado = New Empleado() loEmpleado.psNombre = "Juan" loEmpleado.piCategoria = 1 ' atención, el sueldo para este empleado „ debería estar entre 1 a 200, debido a su categoría loEmpleado.pdbSueldo = 250 End Sub End Module Public Class Empleado Public msNombre As String Public miCategoria As Integer Public mdbSueldo As Double End Class ENCAPSULACIÓN A TRAVÉS DE PROPIEDADES Public Property Sueldo() As Double Get Return mdbSueldo End Get ' cuando asignamos el valor a esta propiedad, ' ejecutamos código de validación en el bloque Set Set(ByVal Value As Double) ' si la categoría del empleado es 1... If miCategoria = 1 Then ' ...pero el sueldo supera 200 If Value > 200 Then ' mostrar un mensaje y asignar un cero Console.WriteLine("La categoría no corresponde con el sueldo") mdbSueldo = 0 Else „ si todo va bien, asignar el sueldo mdbSueldo = Value End If End If End Set End Property PROPIEDADES DE SÓLO LECTURA / ESCRITURA ' esta propiedad sólo permite asignar valores, por lo que no dispone de bloque Get Public WriteOnly Property CuentaBancaria() As String Set(ByVal Value As String) Select Case Left(Value, 4) Case "1111" msEntidad = "Banco Universal" Case "2222" msEntidad = "Banco General" Case "3333" msEntidad = "Caja Metropolitana" Case Else msEntidad = "entidad sin catalogar" End Select End Set End Property ' esta propiedad sólo permite obtener valores, por lo que no dispone de bloque Set Public ReadOnly Property EntidadBancaria() As String Get Return msEntidad End Get End Property WITH…END WITH PARA USAR OBJETOS
Dim loEmp As Empleado = New Empleado()
With loEmp .Nombre = “JUAN" .Apellidos = “PEREZ" .MostrarDatos() End With USO DE ME / MYCLASS Sirven para referenciar cualquier componente dentro de la misma clase. Para diferenciar un atributo de un parámetro o variable.
Public Class Empleado
Public piID As Integer Private msNombre As String Public Sub VerDatos() ' utilizamos Me y MyClass en este método para tomar el valor de la variable ' piID que está en esta misma clase, y para llamar al método NombreMay() ' que también está en la clase Console.WriteLine("Código del empleado: {0}", Me.piID) Console.WriteLine("Nombre del empleado: {0}", MyClass.NombreMay()) End Sub Public Function NombreMay() As String Return UCase(msNombre) End Function End Class ESPACIOS DE NOMBRES El espacio de nombre o Namespace, es utilizado para organizar las clases e identificarlas de forma fácil. Esto se logra utilizando la siguiente instrucción:
Namespace <nombre> Public Class <nombre_clase> ... End Class End Namespace
De esta manera, para hacer referencia a la clase desde un
formulario windows por ejemplo, lo haremos de la forma:
Dim <variable> As New <nombre de espacio>.<clase>
ESPACIOS DE NOMBRES EJEMPLO ESPACIOS DE NOMBRES Module Module1 Sub Main() ' como la clase Factura se encuentra en el espacio de nombres raíz, ' instanciamos normalmente Dim loFac As New Factura() loFac.piID = 5 loFac.piImporte = 200 loFac.Datos() Console.ReadLine() End Sub End Module ' clase Factura ' esta clase se encuentra dentro del espacio de nombres raíz del ensamblado Public Class Factura Public piID As Integer Public piImporte As Integer Public Sub Datos() Console.WriteLine("La factura {0}, tiene un importe de {1}", Me.piID, Me.piImporte) End Sub End Class EJEMPLO ESPACIOS DE NOMBRES clase Empleado esta clase se encuentra dentro del espacio de nombres raíz del ensamblado, y a su vez, dentro del espacio de nombres Personal Namespace Personal Public Class Empleado Public psID As Integer Public Sub MostrarDatos() Console.WriteLine("Identificador del empleado: {0}", Me.psID) Console.ReadLine() End Sub End Class End Namespace debemos importar el espacio de nombres o no podremos instanciar objetos de las clases que contiene Imports ConsoleApplication1.Personal Module Module1 Sub Main() ' como hemos importado el espacio de nombres Personal podemos instanciar „ un objeto de su clase Empleado Dim loEmp As Empleado loEmp = New Empleado() loEmp.piID = 5 loEmp.MostrarDatos() Console.ReadLine() End Sub End Module EJEMPLO 2 ESPACIOS DE NOMBRES Namespace Contabilidad Public Class Cuenta Public piCodigo As Integer Public Function Obtener() As Integer Return Me.piCodigo End Function End Class Public Class Balance Public psDescripcion As String Public Sub MostrarDescrip() Console.WriteLine("La descripción del balance es: {0}",Me.psDescripcion) Console.ReadLine() End Sub End Class End Namespace EJEMPLO 2 ESPACIOS DE NOMBRES Imports ConsoleApplication1.Contabilidad Module Module1 Sub Main() ' instanciamos con sintaxis calificada Dim loCuen As New Contabilidad.Cuenta() Dim liDatoCuenta As Integer loCuen.piCodigo = 158 liDatoCuenta = loCuen.Obtener() ' al haber importado el espacio de nombres podemos instanciar usando el nombre ' de la clase directamente Dim loBal As Balance loBal = New Balance() loBal.psDescripcion = "Resultado trimestral" loBal.MostrarDescrip() Console.ReadLine() End Sub End Module ESPACIO DE NOMBRES DE OTROS ENSAMBLADOS 2.2 INSTANCIACIÓN DE UNA CLASE. 2.3 REFERENCIA AL OBJETO ACTUAL. FASES EN EL INSTANCIADO DE CLASES: OBJETOS Definición de una clase. Declaración de una referencia a un objeto- clase. Creación y referencia de una instancia de la clase (concreción en un objeto determinado). Referencia y acceso al objeto creado: Atributos de clases Atributos de instancia DEFINICIÓN DE UNA CLASE Una clase no es más que una serie de código que define a todos los elementos relacionados con ella (atributos y/o propiedades, métodos y eventos). EJEMPLO DEFINICIÓN DE CLASE public class Circulo „Atributos private r as double „Propiedades public property radio() as double get return r end get set (ByVal value sa double) r=value end set „Metodos public Function calcularArea() as double return (Math.PI*r*r) end function public Function calcularPerimetro() as double return (2*Math.PI*r) end function end class DECLARACIÓN DE UNA REFERENCIA Para la manipulación de una instancia es necesario crear una variable con la cual podamos referenciar a dicho objeto. Una variable por referencia es un apuntador (almacena la dirección de memoria del objeto) a una instancia especifica de la clase. A través de esta variable por referencia se puede manipular las propiedades y métodos de un objeto. Inicialmente una variable por referencia apunta a nada (nothing), es decir la dirección de memoria es nula.
dim objetocirculo as Circulo
CREACIÓN Y REFERENCIA DE UNA INSTANCIA Una instancia es un objeto de una clase en particular. Al proceso de construir un objeto se le llama instanciación. Cuando se construye un objeto es necesario dar un valor inicial a sus atributos, es por ello que existe un método especial en cada clase, llamado constructor, que es ejecutado de forma automática cada vez que es instanciado un objeto. Cada vez que creamos una nueva instancia, ésta adquiere las propiedades, métodos y eventos de la clase a la que pertenece (es lo que permite la relación es un), sin embargo, cada instancia es independiente de las otras; esto nos da dos ventajas: 1. Si hago algún cambio en la clase, todas las instancias de esta clase se actualizarán automáticamente; esto nos permite hacer cambios sin tener que ir a cada una de las instancias (se aplica el mismo principio de herencia, aunque a un nivel diferente). 2. Al ser independientes de las otras instancias, puedo darles valores diferentes sin que afecten a las demás (como tener una silla negra, una roja, una más alta, etc.). Aunque comparten la misma estructura, pueden programarse individualmente, dando versatilidad y flexibilidad al código. En VB .NET una instancia se crea a partir de utilizar la palabra New y el nombre de la clase (constructor con sus parámetros). A la instancia creada VB le asigna un hashcode único que es la forma de diferenciarla de otras instancias. Una vez creada la instancia se debe asignar a una variable por referencia del tipo de la clase para poder utilizarla. Ejemplo: objetocirculo=New Circulo( ) REFERENCIA Y ACCESO AL OBJETO CREADO Para acceder a un objeto (instancia) se hace uso de la variable por referencia que apunta a dicho objeto. Para hacer uso de las propiedades o métodos del objeto basta con poner el nombre de la variable por referencia, un punto y el nombre de la propiedad o método a utilizar (lo cual se conoce como enviar mensajes al objeto). Ejemplo: objcirculo.radio=200 writeline(“Area={0}“, objcirculo.calcularArea()) MIEMBROS DE DATOS COMPARTIDOS (ATRIBUTOS DE CLASE ) En ocasiones es necesario o conveniente generar elementos que tomen un mismo valor para cualquier número de instancias generadas o bien invocar/llamar métodos sin la necesidad de generar instancias, y es bajo estas dos circunstancias que es empleado el calificador shared. Los miembros de datos compartidos permiten que múltiples instancias hagan referencia a una única variable de nivel de clase. Cuando se usa la palabra clave shared, la variable es única para todas las instancias (objetos) de la clase (ocupa un único lugar en memoria). Las variables de clase se reconocen por la palabra clave shared. NiveldeAcceso Shared MiembrodeDatos As TipodeDatos A las variables de clase se accede mediante el nombre de la clase: <nombre de la clase>.<propiedad o método de clase> Math.PI Los miembros de datos compartidos están directamente enlazados a la clase, y podemos declararlos como públicos o privados. Si declaramos los miembros de datos como públicos, estarán accesibles para cualquier código que pueda acceder a la clase. Si declaramos los miembros de datos como privados, proporcionaremos propiedades compartidas públicas para acceder a la propiedad compartida privada. MÉTODOS COMPARTIDOS (MÉTODOS DE CLASE ) Podemos utilizar los miembros de procedimiento compartidos para diseñar funciones que pueden ser invocadas sin crear una instancia de la clase. Los procedimientos compartidos son métodos de una clase que no están asociados a una instancia específica de una clase. Los miembros de procedimiento compartidos únicamente pueden acceder a datos marcados con la palabra clave Shared. Por ejemplo, un método compartido no puede hacer referencia a un miembro de la instancia de una clase. ' Código TestClass Public Shared Function GetComputerName( ) As String ... End Function ' Código cliente MessageBox.Show(TestClass.GetComputerName( )) El cliente únicamente necesita hacer referencia al método prefijado por el nombre de la clase, ya que no se requiere ninguna instancia de la clase. ATRIBUTOS DE INSTANCIA No se usa shared, el sistema crea un lugar nuevo para esa variable con cada instancia (o sea que es independiente para cada objeto). Las variables de instancia se pueden acceder desde cualquier parte de la clase. Las variables de instancia si son públicas se pueden acceder desde otra clase por medio de los objetos: objeto.nombreVariable Si las variables de instancia son privadas (private) se deben acceder a través de métodos set y get (property). 2.4 MÉTODOS CONCEPTO DE MÉTODO Es la implementación de un algoritmo que representa una operación o función que un objeto realiza. El conjunto de los métodos de un objeto determinan el comportamiento del objeto. Un método es un conjunto de instrucciones a las que se les da un determinado nombre de tal manera que sea posible ejecutarlas en cualquier momento sin tenerlas que reescribir sino usando sólo su nombre. A estas instrucciones se les denomina cuerpo del método, y a su ejecución a través de su nombre se le denomina llamada al método. La ejecución de las instrucciones de un método puede producir como resultado un objeto de cualquier tipo. A este objeto se le llama valor de retorno del método y es completamente opcional, pudiéndose escribir métodos que no devuelvan ninguno. La ejecución de las instrucciones de un método puede depender del valor de unas variables especiales denominadas parámetros del método, de manera que en función del valor que se dé a estas variables en cada llamada la ejecución del método se pueda realizar de una u otra forma y podrá producir uno u otro valor de retorno. Al conjunto formado por el nombre de un método y el número y tipo de sus parámetros se le conoce como signatura del método. La signatura de un método es lo que verdaderamente lo identifica, de modo que es posible definir en un mismo tipo varios métodos con idéntico nombre siempre y cuando tengan distintos parámetros. Cuando esto ocurre se dice que el método que tiene ese nombre está sobrecargado. CONTROL DE FLUJO DE MÉTODOS El método main es invocado por el sistema cuando se ejecuta un programa (compilado). Cada llamada a métodos regresa al lugar que lo llamó. DECLARACIÓN DE MÉTODOS En VB .NET un método puede ser una Subrutina (Sub) o Función (Function). Una función puede regresar un valor u objeto (tiene valor de retorno). Subrutinas o procedimientos: <visibilidad> Sub nombreMetodo(<ByVal|ByRef> param1 as Tipo, <ByVal|ByRef> param2 as Tipo,…) <sentencias o implementación> End Sub Signatura o Funciones: firma <visibilidad> Function nombreMetodo(<ByVal|ByRef> param1 as Tipo, <ByVal|ByRef> param2 as Tipo,…) as TipoRetorno <sentencias o implementación> RETURN datoTipoRetorno End Function donde: visibilidad: (public, private, protected, sin nada) Para cada parámetro se debe especificar el tipo de dato El tipo de dato de retorno debe coincidir con el dato que regresa mediante la clausula return. EJEMPLOS public Sub depositar(ByVal cantidad as double) saldo=saldo+cantidad End Sub
public Function suma(ByVal a as Integer,
ByVal b as Integer) as Integer return (a+b) End Function
public Function division(ByVal a as double,
ByVal b as double) as double return (a/b) End Function MENSAJES Una aplicación orientada a objetos consiste en un número determinado de objetos que interactúan entre si enviándose mensajes unos a otros para invocar sus métodos. Este intercambio de mensajes facilita su comportamiento, cambios de estado, destrucción o almacenamiento. Tras la recepción de un mensaje el objeto actuará. La acción puede ser el envío de otros mensajes, el cambio de su estado, o la ejecución de cualquier otra tarea que se requiera que haga el objeto. Un método se implementa en una clase, y determina cómo tiene que actuar el objeto cuando recibe un mensaje. Cuando un objeto A necesita que el objeto B ejecute alguno de sus métodos, el objeto A le manda un mensaje al objeto B. Al recibir el mensaje del objeto A, el objeto B ejecutará el método adecuado para el mensaje recibido. EJEMPLO MENSAJES INVOCACIÓN DE MÉTODOS Hay métodos denominados de clase o compartidos. Se reconocen por la palabra clave shared. Para acceder a un método que no es compartido se hace a través de los objetos o instancias: objeto.nombreMetodo(argumento1,argumento2,argumento3)
Para acceder a un método de clase se hace a través de la
clase o de sus objetos o instancias: objeto.nombreMetodo(argumento1,argumento2,argumento3) clase.nombreMetodo(argumento1,argumento2,argumento3)
Se debe tener sumo cuidado que los argumentos que se
colocan en la invocación al método sean del mismo tipo que los del método y en su orden PASO DE PARÁMETROS1 Cuando se escribe un método, se declara el número y tipo de los parámetros requeridos por ese método. Esto se hace en la firma o signatura del método. El conjunto de parámetros de cualquier método es una lista de declaraciones de variables delimitadas por comas donde cada declaración de variable es un par: <ByVal|ByRef> parametro as TipoDato Se utiliza el nombre del parámetro para referirse al valor del parámetro. En VB .Net, se puede pasar como parámetro a un método cualquier tipo de dato válido. Esto incluye tipos primitivos, como enteros, dobles, etc.. y tipos de referencia como arrays, String, objetos, etc… PASO DE PARÁMETROS2 Los parámetros son canales de comunicación para pasar datos entre objetos y sus métodos. Los parámetros van asociados a variables, constantes, expresiones, etc., y, por tanto, se indican mediante los correspondientes identificadores o expresiones. Los parámetros que se utilizan en la llamada o invocación al método se denominan parámetros actuales, reales o argumentos, y son los que entregan la información al método. Los parámetros que la reciben en el método se denominan parámetros formales o ficticios y se declaran en la cabecera, signatura o firma del método. Algunos procedimientos carecen de parámetros cuando se realizan tareas que no requieren recibir información del programa principal. En una llamada a un método o subprograma tiene que verificarse que: 1. El número de parámetros formales debe ser igual al de actuales. 2. Los parámetros que ocupen el mismo orden en cada una de las listas deben ser compatibles en tipo. PARÁMETROS POR VALOR (BYVAL) Cuando un parámetro actual se pasa por valor, el método hace una copia del valor de éste en una posición de memoria idéntica en tamaño pero distinta en ubicación a la del parámetro actual y la asigna al parámetro formal correspondiente. Como el método trabaja a partir de sus parámetros formales, si durante la ejecución se modifica el valor de un parámetro formal correspondiente a un paso por valor, el contenido de la posición de memoria del parámetro actual no se verá alterado. Puede decirse que el paso por valor es un canal de transferencia de información con una sola dirección, es decir, de entrada al método. Cuando se le llama, el método recibe el valor de la variable pasada. Cuando el argumento es de un tipo primitivo, pasar por valor significa que el método no puede cambiar el valor. Cuando el argumento es del tipo de referencia, pasar por valor significa que el método no puede cambiar el objeto referenciado, pero si puede invocar a los métodos del objeto y puede modificar las variables accesibles dentro del objeto. El método obtiene su propia copia de los valores para utilizarlos dentro del ámbito del método. Cualquier cambio realizado en estas copias locales no será reflejado en las variables originales del llamador. El paso de las variables por valor le ofrece alguna seguridad a los programadores: los métodos no puede modificar de forma no intencionada una variable que está fuera de su ámbito. EJEMPLO PARÁMETROS POR VALOR (BYVAL) Module PorValor Sub main() Dim a as Integer=100 Dim b as Integer=200 Console.writeline(“La suma={0}”,suma(a,b)) Console.writeline(“a={0} y b={1}” ,a,b) Console.readline() End Sub End Module
Function suma(ByVal a as Integer, ByVal b as Integer) as Integer
a=a*10 b=b*10 Return (a+b) End Function ¿Qué Imprime el programa y porque? La suma=3000 a=100 y b=200 PARÁMETROS POR REFERENCIA (BYREF) En el paso por referencia el parámetro formal queda asociado a la misma posición de memoria que su correspondiente parámetro actual, por lo que cualquier modificación que el método o función miembro realice sobre el contenido del parámetro formal se efectúa sobre el parámetro actual correspondiente y repercutirá en el programa principal o llamador. De todo esto se deduce que si no queremos que un método o función altere el contenido de un parámetro actual, es decir, de una variable del programa principal o invocador, debemos realizar paso por valor. Por el contrario, si queremos que un método o función altere el valor de un parámetro actual tenemos que pasarlo por referencia. Si un parámetro actual es pasado por referencia, este parámetro no puede ser ni una constante, ni una expresión, sino que debe ser una variable u objeto, ya que no pueden modificarse los contenidos de una constante ni de una expresión. Los objetos y arrays también son pasados por valor, pero el valor de un objeto es una referencia. Entonces el efecto es que los argumentos de tipos de referencia son pasados por referencia. De aquí el nombre. Una referencia a un objeto es la dirección del objeto en la memoria. Ahora, el argumento en el método se refiere a la misma posición de memoria que el llamador. EJEMPLO PARÁMETROS POR REFERENCIA (BYREF) Module PorReferencia Sub main() Dim a as Integer=100 Dim b as Integer=200 Console.writeline(“La suma={0}”,suma(a,b)) Console.writeline(“a={0} y b={1}” ,a,b) Console.readline() End Sub End Module
Function suma(ByRef x as Integer, ByRef y as Integer) as Integer
x=x*10 y=y*10 Return (x+y) End Function ¿Qué Imprime el programa y porque? La suma=3000 a=1000 y b=2000 RETORNO DE VALORES (CLAUSULA RETURN) VB .NET necesita que un método (función) declare el tipo de dato del valor que devuelve. Los métodos o funciones pueden devolver tipos de datos primitivos o tipos de datos de referencia. Los métodos utilizan el operador return para devolver un valor. También se puede ultilizar en lugar de return la sasignación del valor o dato a regresar al nombre de la función. NombreFuncion=DatoaRegresar Return DatoaRegresar El tipo de dato del valor devuelto por la sentencia return debe corresponder con el tipo de dato que el método tiene que devolver; no se puede devolver un objeto desde un método que fue declarado para devolver un entero. Cuando se devuelva un objeto, el tipo de dato del objeto devuelto debe ser una subclase o la clase exacta indicada. Cuando se devuelva un tipo interface, el objeto retornado debe implementar el interface especificado. EJEMPLO DE VALOR DE RETORNO (FUNCIONES) public class Calculadora public shared Function sumar(ByVal a as Double, ByVal b as Double) as Double return (a+b) End Function public shared Function restar(ByVal a as Double, ByVal b as Double) as Double restar=a-b End Function public shared Function multiplicar(ByVal a as Double, ByVal b as Double) as Double return (a*b) End Function public shared Function dividir(ByVal a as Double, ByVal b as Double) as Double if (b>0) then return (a/b) else messagebox.show(“División por cero”) return 0 end if End Function End class 2.5 CONSTRUCTORES Y DESTRUCTORES INICIALIZACIÓN DE ATRIBUTOS DE UN OBJETO VB .Net inicializa siempre con valores por defecto las variables miembro de clases y objetos. El segundo paso en la inicialización correcta de objetos es: Durante la declaración de la variable: public class Miclase public variable as String=“ITZ” public a as Integer=10 Public arreglo( ) as Integer= {10,15,20} End Class Constructores: un método constructor inicializa los miembros de su clase. El programador escribe código para el constructor, que se invoca cada vez que un objeto de esa clase es instanciado. Las variables de Instancia puede ser inicializadas implícitamente a sus valores por defecto (0 para tipos numéricos primitivos, False para booleanos y nada para las referencias). CONCEPTO DE MÉTODO CONSTRUCTOR1 Todas las clases VB .Net tienen métodos especiales llamados Constructores que se utilizan para inicializar un objeto nuevo de ese tipo. Un constructor es un método que es invocado cada vez que se crea una nueva instancia de la clase y sirve para inicializar los atributos o variables miembros de una clase en valores coherentes de acuerdo a los requerimientos. Son Métodos que se ejecutan automáticamente al crear los objetos (instancias) de una clase (i.e. al reservar memoria para los objetos, i.e. al invocar a new). Generalmente son utilizados para: Valores iniciales para las variables de los objetos Otras operaciones de inicialización Simplificación de la sintaxis Encapsulamiento de las variables de los objetos: evitar el acceso externo CARACTERÍSTICAS DE UN CONSTRUCTOR1 Los constructores no tienen valor de retorno y su nombre es siempre New. Si el programador no prepara ningún constructor para una clase, el compilador crea un constructor por defecto, inicializando las variables de los tipos primitivos a su valor por defecto, y los Strings y las demás referencias a objetos a nothing. Si se crea un constructor (incluyendo uno con parámetros), el constructor por default no será creado. Si se proporciona más de un constructor, los parámetros de cada uno de los constructores deben diferenciarse en el número o tipo. Los constructores pueden tener también los modificadores de acceso public, private, protected o nada. Si un constructor es private, ninguna otra clase puede crear un objeto de esa clase. En este caso, puede haber métodos public y shared(factory methods) que llamen al constructor y devuelvan un objeto de esa clase. CARACTERÍSTICAS DE UN CONSTRUCTOR2 Si una clase tiene varios constructores, se diferencian por el tipo y número de sus parámetros (son un ejemplo típico de métodos sobrecargados). Se llama constructor por defecto al constructor que no tiene parámetros. Un constructor de una clase puede llamar a otro constructor previamente definido en la misma clase por medio de la palabra MyClass.New() o Me.New(). En este contexto, la palabra MyClass.New() sólo puede aparecer en la primera sentencia de un constructor. El constructor de una clase derivada puede llamar al constructor de su clase base por medio de la palabra MyBase.New(), seguida de los argumentos apropiados entre paréntesis. De esta forma, un constructor sólo tiene que inicializar por sí mismo las variables no heredadas. Dentro de una clase, los constructores sólo pueden ser llamados por otros constructores o por métodos shared. No pueden ser llamados por los métodos de objeto de la clase. PROCESO DE CREACIÓN DE UN OBJETO (INSTANCIA)
1. Al crear el primer objeto de la clase o al
utilizar el primer método o variable shared se localiza la clase y se carga en memoria. 2. Se ejecutan los inicializadores (sólo una vez). 3. Cada vez que se quiere crear un nuevo objeto: se comienza reservando la memoria necesaria se da valor por defecto a las variables miembro de los tipos primitivos. se ejecutan los inicializadores de objeto. se ejecutan los constructores. OBSERVACIONES Visual Basic inicializa las variables declaradas a sus valores por defecto en tiempo de ejecución. Las variables se pueden inicializar cuando se declaran ya sea en el cuerpo de la clase o en un constructor. Independientemente de si una variable de instancia es inicializada en un constructor, esa variable se inicializa (ya sea en su valor predeterminado o el valor asignado en su declaración) en tiempo de ejecución antes de que los constructores son llamados. Las clases pueden contener constructores sobrecargados para proporcionar varias formas de inicializar los objetos de esa clase. Un constructor sin argumentos puede ser invocado solo si no se definieron constructores para la clase (el constructor por defecto es llamado) o si la clase incluye explícitamente un constructor por defecto. CREAR INSTANCIAS USANDO CONSTRUCTORES Cuando se crea un objeto de una clase, el programador puede proveer inicializadores dentro de paréntesis a la derecha del nombre de la clase. Estos inicializadores son argumentos del constructor de la clases. La declaración seria: Dim objectReference As New ClassName( arguments ) Donde objectReference es una referencia del tipo de dato apropiado, New indica que un objeto esta siendo creado, ClassName indica el tipo de el nuevo objeto y arguments especifica los valores usados por el constructor de la clase para inicializar el objeto. Un constructor que toma argumentos frecuentemente es llamado un constructor parametrizado. EJEMPLO CONSTRUCTOR1 public class MiClase private a, b, c as Integer „Metodos Constructores sobrecargados Sub New( ) „Constructor por defecto End Sub Sub New(ByVal a as Integer) Me.a=a End Sub Sub New(ByVal a as Integer, ByVal b as Integer) MyClass.New(a) „Invoca a constructor anterior Me.b=b End Sub Sub New(ByVal a as Integer, ByVal b as Integer, ByVal c as Integer) MyClass.New(a,b) „Invoca a constructor anterior Me.c=c End Sub End Class EJEMPLO CONSTRUCTOR2 Module UsaMiClase Sub main() „Se crean 3 referencias a instancias de tipo Miclase Dim obj1,obj2,obj3 ,obj4 as MiClase „ Existen 4 formas de crear objetos obj1=New MiClase( ) „invoca a constructor por defecto obj2=New MiClase(10) „invoca al segundo constructor obj3=New MiClase(10,20) „invoca al tercer constructor obj4=New MiClase(10,20,30) „invoca al ultimo constructor End Sub End Module
¿Qué valores tiene cada instancia?
CONCEPTO DE MÉTODO DESTRUCTOR En VB .Net no hay destructores como en C++. VB .Net trabaja bajo el esquema de administración de memoria automática. El sistema se ocupa automáticamente de liberar la memoria de los objetos que ya han perdido la referencia, esto es, objetos que ya no tienen ningún nombre que permita acceder a ellos, por ejemplo: por haber llegado al final del bloque en el que habían sido definidos porque a la referencia se le ha asignado el valor nothing porque a la referencia se le ha asignado la dirección de otro objeto A esta característica de VB se le llama recolección de basura (garbage collection). GARBAGE COLLECTION El gestor de memoria del motor de ejecución .NET (CLR) libera a la persona que programa de la responsabilidad tener que mantener un seguimiento de la utilización de la memoria y de tener que liberar los bloques de memoria que han sido reservados durante la ejecución de la aplicación y que posteriormente no son necesarios. Esta facilidad simplifica la programación en comparación a otros entornos donde la gestión de memoria se ha de hacer explícitamente. Este modelo de gestión de la memoria es conocido como Recolección de Basura (Garbage Collection). Una forma de hacer que un objeto quede sin referencia es cambiar ésta a nothing, haciendo por ejemplo: ObjetoRef= nothing En VB .Net no se sabe exactamente cuándo se va a activar el garbage collector. Si no falta memoria es posible que no se llegue a activar en ningún momento. No es pues conveniente confiar en él para la realización de otras tareas más críticas. Se puede llamar explícitamente al garbage collector haciendo uso de la clase System.GC (método Collect()), aunque esto es considerado por el sistema sólo como una “sugerencia” al CLR. MÉTODOS FINALIZADORES Un finalizador es un método que se llama automáticamente cuando se va a destruir un objeto (antes de que la memoria sea liberada de modo automático por el sistema). Se utilizan para ciertas operaciones de terminación distintas de liberar memoria (por ejemplo: cerrar ficheros, cerrar conexiones de red, liberar memoria reservada por funciones nativas, etc.). Hay que tener en cuenta que el garbage collector sólo libera la memoria reservada con new. Si por ejemplo se ha reservado memoria con funciones nativas en C (por ejemplo, utilizando la función malloc()), esta memoria hay que liberarla explícitamente utilizando el método finalize(). MÉTODO FINALIZE() Un finalizador es un método de objeto (no shared), sin valor de retorno, sin argumentos y que siempre se llama finalize(). Los finalizadores se llaman de modo automático siempre que hayan sido definidos por el programador de la clase. Para realizar su tarea correctamente, un finalizador debería terminar siempre llamando al finalizador de su clase base. Tampoco se puede saber el momento preciso en que los finalizadores van a ser llamados. En muchas ocasiones será conveniente que el programador realice esas operaciones de finalización de modo explícito mediante otros métodos que él mismo llame. Finalize está protegido y, por lo tanto, sólo se puede obtener acceso a él a través de esta clase o de una clase derivada. Este método se invoca de forma automática, después de que un objeto pase a ser inaccesible, salvo que haya sido excluido del proceso de finalización mediante una llamada a SuppressFinalize. Durante el apagado de un dominio de aplicación, se llama a Finalize automáticamente en los objetos que no están exentos de la finalización, incluso aquéllos que todavía son accesibles. Finalize se llama automáticamente sólo una vez en una instancia determinada, a menos que el objeto se registre de nuevo mediante un mecanismo como ReRegisterForFinalize y como consecuencia no se ha llamado a GC.SuppressFinalize. CARACTERÍSTICAS DEL MÉTODO FINALIZE() Permite que un objeto Object intente liberar recursos y realizar otras operaciones de limpieza antes de que el objeto Object sea reclamado por el recolector de elementos no utilizados. Las operaciones de Finalize tienen las siguientes limitaciones: El momento exacto en que se ejecuta el finalizador durante la recolección de elementos no utilizados no está definido. No se garantiza la liberación de recursos en un momento concreto, a menos que se llame a un método Close o a un método Dispose. No se garantiza que los finalizadores de dos objetos se ejecuten en un orden determinado, aunque un objeto haga referencia al otro. Es decir, si el objeto A hace referencia al objeto B y ambos tienen finalizadores, puede que el objeto B ya haya terminado cuando se inicie el finalizador del objeto A. No se ha especificado el subproceso en el que se ejecuta el finalizador. Todas las implementaciones de Finalize en un tipo derivado deben llamar a la correspondiente implementación de tipo base de Finalize. Este es el único caso en el que se permite al código de la aplicación llamar a Finalize. Su sintaxis es: Protected Overridable Sub Finalize () 2.6 SOBRECARGA DE MÉTODOS SOBRECARGA DE MÉTODOS Sobrecarga es la práctica de proporcionar más de una definición para una propiedad o nombre de procedimiento determinados en el mismo ámbito. La nueva declaración de una propiedad o un procedimiento con una firma diferente se llama a veces ocultación por firma. VB .Net permite métodos sobrecargados (Overloads), es decir, métodos distintos que tienen el mismo nombre, pero que se diferencian por el número y/o tipo de los argumentos (diferente firma o signatura). Se pueden sobrecargar los constructores de una clase al igual que otros métodos. Se puede llamar a un constructor desde otro constructor usando la palabra Me.New( argumentos). Sólo puede utilizarse Overloads en una propiedad o instrucción de declaración de procedimiento. No se puede especificar Overloads junto con Shadows en la misma declaración de procedimiento. PROCESO EN LA LLAMADA DE UN MÉTODO SOBRECARGADO 1. Si existe el método cuyos argumentos se ajustan exactamente al tipo de los argumentos de la llamada (argumentos actuales), se llama ese método. 2. Si no existe un método que se ajuste exactamente, se intenta promover los argumentos actuales al tipo inmediatamente superior (por ejemplo char a integer, integer a long, float a double, etc.) y se llama el método correspondiente. 3. Si sólo existen métodos con argumentos de un tipo más restringido (por ejemplo, integer en vez de long), el programador debe hacer un cast explícito en la llamada, responsabilizándose de esta manera de lo que pueda ocurrir. 4. El valor de retorno no influye en la elección del método sobrecargado. En realidad es imposible saber desde el propio método lo que se va a hacer con él. 5. No es posible crear dos métodos sobrecargados, es decir con el mismo nombre, que sólo difieran en el valor de retorno. DIFERENCIAS REQUERIDAS PARA MÉTODOS SOBRECARGADOS La firma en esta declaración debe ser diferente de la firma de cada propiedad o procedimiento que sobrecarga. La firma comprende la propiedad o el nombre de procedimiento junto con lo siguiente: el número de parámetros el orden de los parámetros los tipos de datos de los parámetros el número de parámetros de tipo (para un procedimiento genérico) el tipo de valor devuelto (sólo para un procedimiento de operador de conversión) Todas las sobrecargas deben tener el mismo nombre pero cada una debe diferir de todas las demás en una o varias de las consideraciones anteriores. Esto permite al compilador distinguir qué versión debe utilizar cuando el código llama a la propiedad o al procedimiento. DIFERENCIAS NO PERMITIDAS EN SOBRECARGA No está permitido cambiar uno o varios de los siguientes elementos para sobrecargar una propiedad o un procedimiento, porque no forman parte de la firma: si devuelve o no un valor (para un procedimiento) el tipo de datos del valor devuelto (excepto para un operador de conversión) los nombres de los parámetros o parámetros de tipo las restricciones de los parámetros de tipo (para un procedimiento genérico) las palabras clave de modificadores de parámetros (como ByRef o Optional) las palabras clave de modificadores de propiedades o procedimientos (como Public o Shared) MODIFICADOR OVERLOADS Es un modificador opcional. No es necesario utilizar el modificador Overloads cuando se definen varias propiedades o procedimientos sobrecargados en la misma clase. Sin embargo, si utiliza Overloads en una de las declaraciones, debe utilizarlo en todas ellas. Overloads también se puede utilizar para sombrear un miembro existente o un conjunto de miembros sobrecargados, en una clase base. Cuando se utiliza Overloads de esta forma, se declara la propiedad o el método con el mismo nombre y la misma lista de parámetros que el miembro de clase base, y no se proporciona la palabra clave Shadows. El modificador Overloads se puede utilizar en estos contextos: Function (Instrucción) Operator (Instrucción) Property (Instrucción) Sub (Instrucción) EJEMPLO DE SOBRECARGA DE MÉTODOS public class Saludo public shared Overloads Sub saludar() Console.writeLine(“Hola mundo”) End Sub public shared Overloads Sub saludar(Byref frase as String) Console.writeLine(frase) End Sub public shared Overloads Sub saludar(Byref frase as String,Byval n as Integer) for i as integer=1 to n Console.writeLine(frase) next End Sub public shared Overloads Sub saludar(Byref frase as String, Byval nr as Integer, Byval nc as Integer) for i as integer=1 to nr for j as integer=1 to nc Console.write(frase & “ “) next Console.writeline( ) next End Sub End Class REDEFINICIÓN DE MÉTODOS (OVERRIDES) Diferente de la sobrecarga de métodos es la redefinición. Una clase puede redefinir (Overrides) un método heredado (Overridable) de una clase base (superclase). Redefinir un método es dar una nueva definición o implementación. En este caso el método debe tener exactamente los mismos argumentos en tipo y número que el método redefinido (misma firma o signatura). Sólo pude utilizarse Overrides en una instrucción de declaración de procedimiento o propiedad. No se puede especificar Overrides junto con Shadows o Shared en la misma declaración. Dado que un elemento de reemplazo es reemplazable de forma implícita, no se puede combinar Overridable con Overrides. La firma de esta declaración debe coincidir exactamente con la firma de la propiedad o procedimiento que reemplaza. Esto significa que las listas de parámetros deben tener el mismo número de parámetros, en el mismo orden, con los mismos tipos de datos. Además de la firma, la declaración de reemplazo también debe coincidir exactamente con los siguientes elementos: El nivel de acceso El tipo de valor devuelto, si lo hubiese 2.7 SOBRECARGA DE OPERADORES SOBRECARGA DE OPERADORES También es conocida como un método o procedimiento de operador, el cual es una serie de instrucciones que definen el comportamiento de un operador estándar (como *, <> o And) en una clase o estructura definida. Tras definir una clase o estructura, puede declarar las variables para que pertenezcan al tipo de dicha clase o estructura. A veces estas variables deben participar en una operación como parte de una expresión. Para ello, estas variables deben ser un operando de un operador. Puede definir el comportamiento de un operador cuando uno o los dos operandos pertenecen al tipo de la clase o de la estructura. Los procedimientos de operador pueden ser de uno de los siguientes tipos: Una definición de un operador unario donde el argumento pertenece al tipo de la clase o estructura. Una definición de un operador binario donde al menos uno de los argumentos pertenece al tipo de la clase o estructura. Una definición de un operador de conversión donde el argumento pertenece al tipo de la clase o estructura. Una definición de un operador de conversión que devuelve el tipo de la clase o estructura. Los operadores de conversión siempre son unarios y siempre utilizan CType como el operador que se está definiendo. OPERADORES QUE SE PUEDEN SOBRECARGAR Escriba Operadores Unario +, -, IsFalse, IsTrue, Not +, -, *, /, \, &, ^, >>, <<, =, <>, >, >=, <, <=, Binario And, Like, Mod, Or, Xor Conversión CType (unario)
• Observe que el operador = en la lista binaria es el operador de comparación,
no el operador de asignación.
• Cuando define CType, debe especificar Widening o Narrowing.
• Debe definir ciertos operadores como pares correspondientes. Si define un
operador de este tipo, también debe definir el otro. Los pares correspondientes son los siguientes: = y <> >y< >= y <= IsTrue y IsFalse SINTAXIS EN LA DECLARACIÓN La sintaxis para declarar un procedimiento de operador es la siguiente: Public Shared [Widening | Narrowing] Operator operatorsymbol (operand1 [, operand2]) As datatype ' Statements of the operator procedure. End Operator Utilice únicamente la palabra clave Widening o Narrowing en un operador de conversión de tipos. El símbolo del operador siempre es CType (Función) (Visual Basic) en un operador de conversión de tipos. Declare dos operandos para definir un operador binario y declare un operando para definir un operador unario, incluidos los operadores de conversión de tipos. Todos los operandos deben declararse ByVal. Declare cada operando del mismo modo que declara los parámetros de Subprocedimientos (Visual Basic). Como está definiendo un operador de una clase o estructura que ha definido, al menos uno de los operandos debe tener el mismo tipo de datos que la clase o la estructura. En un operador de conversión de tipos, el operando o el tipo de valor devuelto debe pertenecer al tipo de datos de la clase o estructura. EJEMPLO DE SOBRECARGA DE OPERADORES1 Public Class Quebrado 'Atributos Private numerador As Integer Private denominador As Integer 'Metodo Constructor Public Sub New(ByVal numerador As Integer, ByVal denominador As Integer) Me.numerador = numerador Me.denominador = denominador End Sub 'Sobreescritura de Metodos Public Overrides Function ToString() As String 'Representa al objeto como cadena Return (numerador & "/" & denominador) End Function 'Sobrecarga de operadores 'Sobrecarga * para multiplicar quebrados Public Shared Operator *(ByVal q1 As Quebrado, ByVal q2 As Quebrado) As Quebrado Dim resultado As Quebrado resultado=New Quebrado(q1.numerador * q2.numerador, q1.denominador * q2.denominador) Return resultado End Operator End Class EJEMPLO DE SOBRECARGA DE OPERADORES2 Module UsaQuebrados Sub Main() Dim a As New Quebrado(2, 3) Dim b As New Quebrado(1, 2) Dim c As Quebrado c = a * b 'Multiplicación de quebrados: ejecuta el operador sobrecargado Console.WriteLine("{0} * {1} = {2}", a, b, c) Console.ReadLine() End Sub End Module 2.8 ESTRUCTURAS ESTRUCTURAS(STRUCTURE) Una estructura es una combinación de tipos de datos que se crea combinando otros tipos de datos. Las estructuras son de tipo valor (es decir, una variable de tipo estructura contiene los datos de la estructura, en lugar de una referencia a los datos como hace el tipo referencia). Las estructuras pueden tener datos, propiedades, métodos y procedimientos y pueden invocar y manipular eventos. Las estructuras resultan útiles cuando deseamos que una única variable guarde varias piezas de información relacionadas. Después de declarar una estructura, podemos declarar variables de ese tipo. El uso más simple y habitual de las estructuras es encapsular variables relacionadas, creando un tipo de datos definido por el usuario. Ejemplo: Structure Empleado Public Nombre As String Public Extension As Long Private Salario As Decimal End Structure DIFERENCIAS ENTRE CLASES Y ESTRUCTURAS1 Las estructuras son tipos de valor, las clases son tipos de referencia. Las estructuras utilizan asignación de pila y las clases utilizan asignación del montón(Heap). De forma predeterminada, todos los miembros de estructura son Public y las variables y constantes de clase son Private, mientras que otros miembros de clase son Public de forma predeterminada. Los miembros de estructuras no pueden declararse como Protected, a diferencia de los miembros de clase. Los procedimientos de las estructuras no pueden controlar eventos, a diferencia de los procedimientos de clase. Las declaraciones de variables de estructura no pueden especificar inicializadores, la palabra clave New o los tamaños iniciales para matrices; mientras que las declaraciones de variables de clase sí pueden. Las estructuras heredan de forma implícita de la clase ValueType, no pueden heredar de ningún otro tipo de clase. Las clases pueden heredar de cualquier clase o clases que no sean del tipo ValueType. Las estructuras no son heredables; las clases, sí. DIFERENCIAS ENTRE CLASES Y ESTRUCTURAS2 Las estructuras no se terminan nunca, por lo tanto, Common Language Runtime (CLR) nunca llama al método Finalize en una estructura; las clases las termina el recolector de elementos no utilizados, que llama al método Finalize en una clase cuando detecta que no quedan referencias activas.
Las estructuras sólo pueden tener constructores no compartidos si
pueden tomar parámetros; sin embargo las clases pueden tener constructores con o sin parámetros.
Cada estructura tiene un constructor público implícito sin
parámetros. El constructor inicializa todos los miembros de datos de estructura con sus valores predeterminados. Este comportamiento no puede redefinirse. EJEMPLO DE ESTRUCTURAS1 Structure empleado Public rfc As String Public nombre As String Public fechaNac As Date Public edocivil As Integer Public sexo As Char Public Overrides Function ToString() As String Return (rfc & vbCrLf & nombre & vbCrLf & _ fechaNac & vbCrLf & edocivil & vbCrLf & sexo) End Function End Structure EJEMPLO DE ESTRUCTURAS2 Module UsaEstructura Sub Main() Dim persona(10) As empleado persona(0).rfc = "CASA770501HG1" persona(0).nombre = "Juan Perez" With persona(0) .fechaNac = New Date(1977, 5, 1) .edocivil = 1 .sexo = "H"c End With For i As Integer = 1 To persona.GetUpperBound(0) persona(i).rfc = "persona " & i Next For i As Integer = 0 To persona.GetUpperBound(0) Console.WriteLine(persona(i)) Next Console.ReadKey() End Sub End Module