Aínda que pareza unha novidade, a base da programación orientada a obxectos é o obxecto. Na vida real todos os obxectos teñen unha serie de características e comportamentos. Por exemplo, unha porta ten cor, forma, dimensións, material … (gozar dunha serie de características) e pode ser aberto, pechado … (ten un comportamento). Na programación orientada a obxectos, un obxecto é unha combinación de datos e rutinas específicas que poden operar con estes datos. Polo tanto, os dous tipos de compoñentes dun obxecto son:
- campos ou atributos: compoñentes dun obxecto que almacena datos. Tamén se chaman variables membros. Estes datos poden ser de tipo primitivo (
boolean, int, double, char...
) ou, á súa vez, outro tipo de obxecto (o que se chama agregación ou composición de obxectos). A idea é que un atributo representa unha certa propiedade dun obxecto. - rutinas ou métodos: é un compoñente dun obxecto que realiza unha determinada acción ou tarefa cos atributos. En principio, todas as variables e rutinas dun programa Java deben pertencer a unha clase. De feito, en Java non hai ningunha noción de programa principal e subrutinas non existen como unidades modulares independentes, senón que sempre forman parte dalgunha clase.
clases 9.1
Unha clase representa o conxunto de obxectos que comparten unha estrutura e comportamento común. Unha clase é unha combinación específica de atributos e métodos e pode considerarse un tipo de datos de calquera tipo non primitivo. Deste xeito, unha clase é unha especie de modelo de obxectos ou prototipo: define os atributos que compoñen ese tipo de obxectos e métodos que se poden usar para traballar con eses obxectos. Aínda que, por outra banda, unha clase tamén pode estar composta por métodos estáticos que non necesitan obxectos (como clases construídas en capítulos anteriores que conteñen un método estático main
)). A declaración dunha clase segue a seguinte sintaxe:
class IdentificadorClase { // Declaraciones de atributos y metodos ...}
Convención de programadores en Java: Os identificadores das clases deben ser simples , descritivo e substantivo e, no caso de nomes compostos, coa primeira letra de cada unha en maiúsculas. É conveniente usar as palabras completas e evitar acrónimos, a menos que a abreviatura sexa moito máis utilizada que a forma non abreviada como en URL ou HTML.
9.2 instancias
Unha instancia é Un elemento tanxible (ocupa a memoria durante a execución do programa) xerado a partir dunha definición de clase. Todos os obxectos utilizados nun programa deben pertencer a unha clase dada.
Aínda que o termo úsase ás veces dun xeito impreciso, un obxecto é unha instancia dunha clase predefinida en Java ou declarada polo usuario e referida por unha variable que almacena o seu enderezo de memoria. Cando se di que Java non ten punterios, simplemente indícase que Java non ten punteiros que o programador pode ver, xa que todas as referencias de obxectos son de feito indicacións na representación interna.
En xeral, o acceso En atributos faise a través do operador de punto, que separa o identificador da referencia do identificador de atributo (idReferencia.idAtributo
). As chamadas aos métodos para realizar as diferentes accións realízanse separando os identificadores da referencia e do método correspondente co operador de puntos (idReferencia.idMetodo(parametros)
).
Simple Exemplo de clase e instancia
O seguinte código mostra a declaración da clase Precio
. A clase Precio
consiste nun único atributo (euro
) e dous métodos: un que asigna un valor ao atributo (pone
) sen devolver ningún valor e outro que devolva o valor do atributo (da
).
/** * Ejemplo de declaracion de la clase Precio * double da() --> devuelve el valor almacenado en euros * void pone( double x ) --> almacena valor en euros */public class Precio { // Atributo o variable miembro public double euros; // Metodos public double da() { return this.euros; } public void pone(double x) { this.euros = x; }}
Gráfica, unha clase pode ser representada como un rectángulo.
Figura 9.1 Representación gráfica da clase Precio
O código anterior pode ser compilado:
$>javac Precio.java
xerando o ficheiro bytecodes Precio.class
. Este ficheiro non é executable directamente polo intérprete, xa que o código fonte non inclúe ningún método principal (main
).Para probar o código anterior, pódese construír outro ficheiro co código fonte que se mostra a continuación:
/** * Ejemplo de uso de la clase Precio */public class PruebaPrecio { public static void main (String args ) { Precio p; // Crea una referencia de la clase Precio p = new Precio(); // Crea el objeto de la clase Precio p.pone(56.8); // Llamada al metodo pone // que asigna 56.8 al atributo euros // Llamada al metodo da que devuelve el valor de euros System.out.println("Valor = " + p.da()); Precio q = new Precio(); // Crea una referencia y el objeto q.euros=75.6; // Asigna 75.6 al atributo euros System.out.println("Valor = " + q.euros); }}
Figura 9.2 Representación gráfica do Espazo de memoria utilizado polas referencias e instancias da clase Precio
durante a execución do método main
da clase PruebaPrecio
Explicación do exemplo anterior
Para poder traballar con obxectos que terá que seguir un proceso de dous pasos. O primeiro que hai que facer o programa é crear unha referencia ou punteiro da clase Precio
co identificador p
. Similar a como se declara unha variable dun tipo primitivo, a declaración de identificación de referencia está feita coa sintaxe:
identificadorClase identificadorReferencia;// En el ejemplo anterior: Precio p;
Figura 9.3 Creación da referencia p
A referencia ou punteiro, p
, é como unha misión para almacenar o enderezo de memoria de (punto a) os compoñentes da instancia que aínda non foi creada ou referenciada. Neste momento dise que a referencia p
, renovada, almacena un enderezo de memoria nula (que non corresponde a ningún obxecto) ou . O segundo paso do proceso para traballar con obxectos conduce á creación dunha nova instancia referenciada por p
, que se realiza coa declaración:
Figura 9.4 Creación da nova instancia da clase Precio
por p
Esta operación tamén se chama a instanciación. Aínda que as dúas operacións anteriores (creación da referencia e creación da instancia referenciada) pódense realizar en conxunto na mesma liña de código:
identificadorClase identificadorReferencia = new identificadorClase();// En el codigo del ejemplo anterior: Precio q = new Precio();
Figura 9.5 Creación da referencia q
e a nova instancia da clase Precio
referenciada por q
O resultado da execución do código anterior é dúas novas instancias da clase Precio
respectivamente por p
e
. O atributo euro de cada unha das novas instancias da clase Precio
é accesible a través do identificador de referencia e o operador de puntos (p.euros
e ). Os métodos da
e pone
pertencente á clase Precio
son accesibles a través do identificador do referencia e operador de punto (p.da()
e p.pone(56.8)
e q.da()
e , respectivamente). No caso dos métodos, a instancia pola que se fai a chamada correspondente actúa como un parámetro implícito ou argumento do método.
Se unha referencia a outra está asignada por unha declaración de asignación, non se copian Os valores dos atributos, pero que unha soa instancia estaba destinada a dúas referencias diferentes. Por exemplo:
q = p; // Ahora p y q referencian al mismo objeto
Figura 9.6 Resultado da asignación de valores entre referencias
Neste caso. Que pasa coa instancia previamente referenciada por q
? Dixo a instancia queda sen referencia (inaccesible). Isto pode ser un problema nalgúns idiomas de programación, como o caso de Pascal ou C, que utilizan variables dinámicas e que precisan liberar explícitamente o espazo na memoria reservado para as variables que van deixar de ser referenciado. A xestión dinámica da memoria adoita ser unha tarefa complicada para o programador e moi dada á proliferación de erros de execución. Para evitar tales inconvenientes, Java permítelle crear tantas instancias como desexado (coa única limitación da memoria que é capaz de xestionar o sistema), sen que o programador teña que preocuparse por destruír ou liberar cando xa non sexan necesarios.O ambiente de execución de Java elimina automaticamente as instancias cando detecta que non se utilizarán (cando deixan de ser referenciados). Este proceso chámase recollida ou colección de lixo (recollida de lixo).
9.3 modificadores de visibilidade
O modificador indica que o compoñente do O método é accesible fóra do código da clase á que pertence o compoñente a través do operador de punto. O modificador private
indica que o compoñente só é accesible a través dos métodos da propia clase. O modificador protexido verase máis tarde. No seguinte código, o atributo é declarado euros
co modificador private
.
/** * Ejemplo de declaracion de la clase PrecioPrivado * double da() --> devuelve el valor almacenado en euros * void pone( double x ) --> almacena valor en euros * euros --> Atributo de acceso privado */public class PrecioPrivado { // Atributo o variable miembro private double euros; private double euros; // Metodos publicos public double da() { return this.euros; } public void pone(double x) { this.euros = x; }}
Se se constrúe outro código que intenta usar directamente o atributo euros
:
/** * Ejemplo de uso de la clase PrecioPrivado * double da() --> devuelve el valor almacenado en euros * void pone( double x ) --> almacena valor en euros * euros --> Atributo de acceso privado */public class PruebaPrecioPrivado { public static void main (String args ) { PrecioPrivado p = new PrecioPrivado(); // Crea instancia p.pone(56.8); // Asigna 56.8 a euros System.out.println("Valor = " + p.da()); // Asigna 75.6 a euros - ERROR p.euros=75.6; System.out.println("Valor = " + p.euros); // Tambien ERROR }}
Un erro de compilación ocorrerá:
$>javac PruebaPrecioPrivado.javapruebaPrecioPrivado.java:15: euros has private access in precioPrivado p.euros=75.6; ^ pruebaPrecioPrivado.java:16: euros has private access in precioPrivado System.out.println("Valor = " + p.euros); ^
desde o atributo euros
só é accesible a través dos métodos de método da
e pone
.
Usando o modificador private
serve para implementar unha das características de programación orientada a obxectos: a ocultación de información ou encapsulación. Estrictamente falando, a Declaración como pública dun atributo dunha clase non respecta este principio de ocultación de información. Declándoos como privados, non tes acceso directo aos atributos do obxecto fóra do código de clase correspondente e só se pode acceder indirectamente a través dos métodos proporcionados pola propia clase. Unha das vantaxes prácticas de forzar o uso dun método para modificar o valor dun atributo é garantir a consistencia da operación. Por exemplo, un método que asigna valor ao atributo euros
dun obxecto da clase Precio
pode garantir que un valor negativo non será Asignado.
9.4 Clases aniñadas e internas
Unha clase B pode definirse como membro doutra clase A. A estrutura sintáctica é a seguinte:
class ClaseA { ... class ClaseB { ... }}
Dise que ClaseB
é unha clase dada no ClaseA
. A clase anidada só se pode usar dentro da clase de contedores. Este tipo de clases só se constrúen cando a clase anidada só se usa ou ten sentido dentro da clase de contedores. A clase anidada pode ser declarada como static
. Neste caso, a clase anidada chámase clase estatística nidada. Se non, chámase clase interna.
9.5 O operador InstanceOf
O operador instanceof
devolve TRUE ou FALSE se un obxecto pertence ou non unha clase dada. Sintaxe:
identificadorInstancia instanceof identificadorClase