La programación orientada a objetos (POO) es una forma especial de programar, más cercana a como expresaríamos las cosas en la vida real que otros tipos de programación. Cuando comenzamos con este curso de Java, hicimos una introducción en la cual explicamos los principales conceptos de la programación orientada a objetos y en específico en el lenguaje Java.
Conceptos Fundamentales: Clases y Objetos
Las clases son declaraciones de objetos, también se podrían definir como abstracciones de objetos. Esto quiere decir que la definición de un objeto es la clase. Cuando programamos un objeto y definimos sus características y funcionalidades en realidad lo que estamos haciendo es programar una clase. Una clase es una plantilla (molde), que define atributos (lo que conocemos como variables) y métodos. En nuestro ejemplo de la fábrica de galletas, la clase sería uno de los moldes para galletas, junto con los métodos para colorearlas y la receta (método para prepararlas). Una definición de clase o estructura es como un plano técnico que especifica lo que puede hacer el tipo.
Debemos declarar una clase antes de poder crear objetos (instancias) de esa clase. Conviene buscar un nombre de clase lo más próximo a lo que representa. En java las clases son las matrices de las que luego se pueden crear múltiples instancias del mismo tipo. En java, primero deberemos crear una clase antes de poder crear instancias o ejemplares de esa clase.
Un objeto es básicamente un bloque de memoria asignado y configurado según el plano técnico. Los objetos son ejemplares de una clase cualquiera. Cuando creamos un ejemplar tenemos que especificar la clase a partir de la cual se creará. Esta acción de crear un objeto a partir de una clase se llama instanciar (que viene de una mala traducción de la palabra instance que en inglés significa ejemplar). En Java, un objeto es básicamente una instancia de una clase. Un programa puede crear muchos objetos de la misma clase. Los objetos también se denominan instancias y se pueden almacenar en una variable con nombre o en una matriz o colección.
Para crear un objeto en Java hay que instanciarlo. Para instanciar objetos en Java hay que utilizar el operador
new. El código de cliente es el código que usa estas variables para llamar a los métodos y acceder a las propiedades públicas del objeto. Una vez tienes el objeto lo puedes utilizar para ejecutar los métodos descritos en la clase.
Lea también: IVA 21% Excel
Declaración de Atributos en una Clase
Las propiedades o atributos son las características de los objetos. Cuando definimos una propiedad normalmente especificamos su nombre y su tipo. La declaración de los atributos en una clase es exactamente igual a la declaración de cualquier variable tal y como has estudiado en las unidades anteriores y similar a como se hace en cualquier lenguaje de programación. La declaración de un atributo (o variable miembro o variable de objeto) consiste en la declaración de una variable que únicamente existe en el interior del objeto y por tanto su vida comenzará cuando el objeto comience a existir (el objeto sea creado).
Esto significa que cada vez que se cree un objeto se crearán tantas variables como atributos contenga ese objeto en su interior (definidas en la clase, que es la plantilla o "molde" del objeto). En el ejemplo que estamos utilizando de objetos de tipo Punto (instancias de la clase Punto), cada vez que se cree un nuevo Punto p1, se crearán sendos atributos x, y de tipo int que estarán en el interior de ese punto p1. Si a continuación se crea un nuevo objeto Punto p2, se crearán otros dos nuevos atributos x, y de tipo int que estarán esta vez alojados en el interior de p2.
Como puedes comprobar los atributos son variables con un tipo y un identificador. El tipo puede ser cualquiera, desde un primitivo hasta una clase que definas. Lo importante es que el tipo sea el adecuado para la información que contendrá el atributo. Si te fijas, el atributo matricula es de tipo String puesto que las matrículas de los coches pueden contener tanto letras como números.
Componentes de la Declaración de un Atributo
La declaración de atributos puede incluir los siguientes componentes:
- Modificadores: Son palabras reservadas que permiten modificar la utilización del atributo (indicar el control de acceso, si el atributo es constante, si se trata de un atributo de clase, etc.).
- Tipo: Indica el tipo del atributo.
- Nombre: Identificador único para el nombre del atributo.
Nomenclatura y Modificadores de Atributos
Por convenio se suelen utilizar las minúsculas para el nombre del atributo. En caso de que se trate de un identificador que contenga varias palabras, a partir de la segunda palabra se suele poner la letra de cada palabra en mayúsculas. Por ejemplo: primerValor, valor, puertaIzquierda, cuartoTrasero, equipoVecendor, sumaTotal, nombreCandidatoFinal, etc.
Lea también: Guía IVA reducido
Como puedes observar, los atributos de una clase también pueden contener modificadores en su declaración (como sucedía al declarar la propia clase). Estos modificadores permiten indicar cierto comportamiento de un atributo a la hora de utilizarlo.
- Modificadores de acceso: Indican la forma de acceso al atributo desde otra clase. Son modificadores excluyentes entre sí.
- Modificadores de contenido: No son excluyentes.
- Otros modificadores: transient y volatile. El primero se utiliza para indicar que un atributo es transitorio (no persistente) y el segundo es para indicar al compilador que no debe realizar optimizaciones sobre esa variable.
Los atributos static tendrán el mismo valor para todos los objetos. Es decir, si se modifica el valor de un atributo static, el cambio afectará a todos los objetos. En Java, los métodos y variables de clase se crean anteponiendo a su declaración la palabra static.
Declaración de Métodos en una Clase
Los métodos son las funcionalidades asociadas a los objetos. Cuando estamos programando las clases las llamamos métodos. Los métodos son como funciones que están asociadas a un objeto. Los métodos especifican el comportamiento de los objetos de la clase.
Al declarar un método también se debe especificar el tipo y nombre de cada uno de los parámetros o argumentos que reciba el método entre paréntesis. Si un método no tiene parámetros, éste queda vacío (no es necesario escribir void). Dentro de un método, los argumentos pueden tener el mismo nombre que los atributos de la clase; de ser así, los argumentos “ocultan” a los atributos. Los métodos también tienen unas llaves. Estas llaves encerrarán el código Java que realizará la acción.
Normalmente los métodos manipulan los atributos, aunque puede haber métodos que no utilicen los atributos para nada. Los atributos siguen existiendo cuando finaliza la ejecución del método. Como puedes ver los métodos también tienen un identificador (el nombre del método). Debe ser un verbo, empezar en minúscula y cumplir con la sintaxis Camel. Los métodos son bastante complejos y hay muchas cosas que debes tener en cuenta a la hora de definirlos. Por ejemplo, si reciben datos del exterior (como puedes ver tienen unos paréntesis después del identificar) o si devuelven algún resultado (en este caso no, por eso he puesto void antes del identificador).
Lea también: ¿Cómo localizar tus XML del SAT?
Sobrecarga de Métodos
La sobrecarga de métodos se refiere a la posibilidad de que dos o más métodos utilicen el mismo nombre en una clase; para ello, los métodos sólo deben variar los argumentos y, opcionalmente, también pueden tener diferentes valores de retorno. 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. Si no existe un método que se ajuste exactamente, se intenta promover los argumentos actuales al tipo inmediatamente superior (cast implícito) y se llama el método correspondiente. Si sólo existen métodos con argumentos de un tipo más restringido, el programador debe hacer un cast explícito en la llamada, responsabilizándose de esta manera de lo que pueda ocurrir.
El valor de retorno no influye en la elección del método sobrecargado. No es posible crear dos métodos sobrecargados con el mismo nombre y con el mismo tipo y número de parámetros que sólo difieran en el valor de retorno.
Métodos Estáticos o de Clase
Hay métodos que no requieren un objeto para ser invocados, se pueden ejecutar a través de la clase. A estos métodos se les llama métodos de clase o estáticos.
Constructores
Vamos a aprender a crear constructores de los objetos. Los constructores, a pesar de su nombre, no construyen nada. En C# los constructores tienen el mismo nombre que se otorgó a la clase. En los constructores podemos recibir los parámetros que sean necesarios para inicializar los objetos. En los constructores usamos this para referirnos al objeto que se está inicializando en ese momento dado.
Es importante notar que es similar hacer uso de método set para establecer atributos y usar el constructor enviándole parámetros, es decir, el resultado es el mismo al usar un constructor vacío y luego establecer los valores de los atributos por medio de una función set o usar un constructor que reciba una serie de parámetros que usará para establecer valores a los atributos. La diferencia radica esencialmente en la agilidad y número de líneas, al usar el constructor y enviar los parámetros, el constructor hace todas las asignaciones por nosotros y usamos una sola línea de código (normalmente) mientras que al usar métodos set debemos usar un método set por cada atributo y si tenemos cinco o más atributos ya se vuelve un poco molesto hacerlo además de tener que usar un constructor de todas formas.
Clases en Diferentes Lenguajes de Programación
Como ya sabrás, una de las características principales de Java es que es un lenguaje orientado a objetos, por lo que la pieza fundamental para trabajar con este lenguaje son (como ya te imaginarás) los objetos. Lo primero que debes hacer cuando definas una clase en Java es crear un nuevo archivo .java. Los nombres de las clases en Java siempre empiezan en mayúscula y cumplen con la sintaxis Camel. Fíjate que utilizo la palabra reservada class y a continuación el nombre de la clase con la primera letra en mayúscula: public class Coche. A continuación del nombre de la clase se abre una llave y su correspondiente llave de cierre está al final. El objeto es miCoche. Recuerda que la clase Coche es un tipo de dato, por eso lo declaro así: Coche miCoche. Primero el tipo y luego el identificador.
En C#, incluso en el más básico, lo que nos vamos a encontrar son clases de programación orientada a objetos, en un número que dependerá de la complejidad de la aplicación. Como puedes ver una clase se define con la palabra reservada "class". En C# podemos declarar propiedades de las clases simplemente indicando su nombre y su tipo. Además a las propiedades les podemos asignar una visibilidad, indicando si son públicas, privadas, etc. En este caso hemos definido un método llamado "show". Se antepone la palabra "void" porque en C# debemos indicar el tipo de datos que devuelve todo método. Luego colocamos los paréntesis y opcionalmente parámetros que el método necesite recibir en su invocación. En el caso de los métodos también podemos indicar la visibilidad, como public o private.
En C++, la primera palabra que aparece es lógicamente class que sirve para definir una clase y para declarar objetos de esa clase. Su uso es parecido a la ya conocida struct: class
Clases vs. Estructuras y Comparación de Objetos
Dado que las clases son tipos de referencia, una variable de un objeto de clase contiene una referencia a la dirección del objeto en el montón administrado. Si se asigna una segunda variable del mismo tipo a la primera variable, ambas variables hacen referencia al objeto en esa dirección. Las instancias de clases se crean mediante el operador
new.
Dado que los structs son tipos de valor, una variable de un objeto struct contiene una copia de todo el objeto. La memoria para p1 y p2 se asigna en la pila de subprocesos. Esta memoria se reclama junto con el tipo o método en el que se declara. Este es uno de los motivos por los que se copian las estructuras en la asignación. En contraste, la memoria asignada para una instancia de clase es recuperada automáticamente (recolección de basura) por el Common Language Runtime cuando todas las referencias al objeto están fuera de alcance. No es posible destruir de forma determinista un objeto de clase como puede en C++.
Al comparar dos objetos para obtener igualdad, primero debe distinguir si desea saber si las dos variables representan el mismo objeto en la memoria o si los valores de uno o varios de sus campos son equivalentes. Para determinar si dos instancias de clase hacen referencia a la misma ubicación en la memoria (lo que significa que tienen la misma identidad), use el método estático
Object.ReferenceEquals. El método
ValueType.Equals, de forma predeterminada, determina si los campos de instancia de dos instancias de estructura tienen los mismos valores. La implementación predeterminada
System.ValueTypede
Equalsusa boxing y reflection en algunos casos. Para determinar si los valores de los campos de dos instancias de clase son iguales, es posible que pueda usar el método
Equalso el operador
==. En cambio, úselos solo si la clase los ha invalidado o sobrecargado para proporcionar una definición personalizada de lo que significa "igualdad" para los objetos de ese tipo. La clase también puede implementar la
IEquatableinterfaz o la
IEqualityComparerinterfaz. Ambas interfaces proporcionan métodos que se pueden usar para probar la igualdad de valores.
