51
A3F POO en lenguajes compilados de tipos estáticos (Java y C#) Carlos Fontela [email protected]

POO en lenguajes compilados de tipos estáticos (Java …materias.fi.uba.ar/7507/content/20101/7507_05_POO_JavaCs.pdf · Arrays.sort(v); doublex = Math.pow ... Arreglos “primitivos”no

  • Upload
    vudung

  • View
    225

  • Download
    0

Embed Size (px)

Citation preview

A3F

POO en lenguajes

compilados de tipos

estáticos (Java y C#)

Carlos Fontela

[email protected]

2c2009 2

A3F

Temario

Modelo de referencias, creación y destrucción de objetos

(introducción)

Paquetes y grupos de clases

Constructores

Excepciones: captura y lanzamiento

Visibilidad

Herencia y transformaciones de tipos

Polimorfismo básico (basado en herencia)

2c2009 3

A3F

Creación de objetos

Declaración:

ArrayList x;

Definición:

x = new ArrayList( );

Significado

ArrayList es la clase de x

ArrayList( ) es el “constructor” de la clase ArrayList

El objeto se crea recién cuando llamo al constructor con el operador “new”

En x queda una referencia a un objeto de tipo ArrayList

2c2009 4

A3F

ReferenciasLas variables son referencias a objetos:

Date x, y;

x = new Date (2009, 7, 25);

y = x;

“x” e “y” referencian al mismo objeto

(hay una sola llamada a constructor)

Si hago:

y = new Date (1950, 8, 17);

Ahora “y” referencia a otro objeto

Una variable que no referencia un objeto tiene el valor “null”

Puedo hacer: Date x = null;

2c2009 5

A3F

Recolección de basura

Si hago:

Date x;

x = new Date (2009, 7, 25);

x = new Date (1950, 8, 17);

El objeto inicial quedó como

basura

Java y C#

2c2009 6

A3F

Paquetes

Agrupación de clases, anidables

Para manejar complejidad y resolver nombres

Ejemplos:

ArrayList es java.util.ArrayList (Java)

ArrayList es System.Collections.ArrayList (C#)

import java.util.*; // Java

import java.util.ArrayList; // Java

using System.Collections; // C#

En Java no es necesario importar las clases de java.lang

2c2009 7

A3F

Paquetes y fuentes

Toda clase está en un paquete

En Java existe el paquete “default”, pero no es recomendable usarlo

En C#, se enmarca el código de la clase en una cláusula “namespace”:

namespace carlosFontela.cuentas { … }

En Java, cada clase pública va en un archivo fuente separado

El paquete se indica en una cláusula “package”

package carlosFontela.cuentas;

2c2009 8

A3F

Implementaciones de mensajes en C#

C# distingue “métodos” de “propiedades”

Métodos: para comportamiento de los objetos

lista.Add(-4);

saludo2 = s.Replace (‘a’, ’u’);

Propiedades: para consultar el estado

Console.WriteLine (lista.Count);

int longitud = saludo.Length;

En C# hay propiedades de clase:

DateTime ahora = DateTime.Now;

“Now” es una propiedad de clase de la clase “DateTime”

2c2009 9

A3F

Implementación de una clase (1)

public class CuentaBancaria {

// atributos:

private int numero;

private String titular;

private double saldo;

// propiedad (sólo lectura):

public double getSaldo ( ) {

return saldo;

}

2c2009 10

A3F

Implementación de una clase (2)

// métodos:

public void depositar (double monto) {

if (monto < 0)

throw new IllegalArgumentException ( );

saldo += monto;

}

public void extraer (double monto) {

if (monto > saldo)

throw new IllegalArgumentException ( );

saldo -= monto;

}

2c2009 11

A3F

Referencia this

Objeto o referencia “this”

public void depositar (double monto) {

if (monto < 0)

throw new IllegalArgumentException ( );

this.saldo = this.saldo + monto;

}

Invocación con el “objeto actual”

c.depositar (2000);

“this” referencia al “objeto actual”

2c2009 12

A3F

Implementación de una clase (3)

// constructor:

public CuentaBancaria (int numero, String titular) {

if (numero <= 0 || titular == null || titular == “”)

throw new IllegalArgumentException ( );

this.numero = numero;

this.titular = titular;

this.saldo = 0;

}

} // fin de la clase

2c2009 13

A3F

¿Y en C#?

Hay propiedades como elemento del lenguaje

Uso:

Console.WriteLine ( c.Saldo );

Definición:

public double Saldo {

get {

return saldo;

}

}

2c2009 14

A3F

Excepciones: captura

Recordemos que las excepciones son objetos

Se acceden mediante variables que los referencian

Tienen estado, comportamiento e identidad

Por ejemplo:

try {

ArrayList lista = new ArrayList (-5);

}

catch (IllegalArgumentException e) {

e.printStackTrace();

}

2c2009 15

A3F

Excepciones: lanzamiento

Se crean y se lanzan hacia el módulo invocante

Sintaxis:

throw new ClaseException ( );

2c2009 16

A3F

Constructores

Se usan para inicializar

Si no se implementan hay uno por omisión

Para que toda clase tenga el suyo

Pero se pueden programar otros, como hicimos

En este caso, deja de existir el default

Debería dejar al objeto en un estado válido

=> debe cumplir con los invariantes

El default no es seguro

2c2009 17

A3F

Visibilidad (1)

Atributos, propiedades y métodos privados

Sólo se pueden usar desde dentro de la clase en que

están definidos

Atributos, propiedades y métodos públicos

Se los puede usar desde cualquier lado

Visibilidad de paquete (default, en Java)

Se los puede usar desde su mismo paquete

2c2009 18

A3F

Visibilidad (2)

Atributos y métodos protegidos (protected)

Son visibles sólo para las clases descendientes y las del propio

paquete

Poco uso; riesgos

Clases con visibilidad “de paquete”

Sólo se pueden usar dentro de su paquete

¿Clases privadas?

Sólo cuando son clases internas

No hay clases protegidas

2c2009 19

A3F

Atributos de clase

Supongamos que necesitamos que el número de

cuenta fuera incremental

Solución:

Agregar un atributo “numeroAcumulado” que mantenga

un único valor para la clase

Eso es un atributo de clase

En Java y C# “de clase” se dice “static”

OJO: Los miembros de clase no se heredan

2c2009 20

A3F

Java y .NET: clases utilitarias

En Java y .Net toda función debe ir en una clase

Aunque trabajemos sin objetos

Usual agrupar funciones

Clase utilitaria

Agrupa métodos estáticos y/o constantes en una clase

Esta clase no se puede instanciar

Ejemplos

Arrays.sort(v);

double x = Math.pow(2,3);

double p = Math.PI;

2c2009 21

A3F

Java y .NET: sobrecarga

public CuentaBancaria (int numero, String titular) {

this ( numero, titular, 0);

}

public CuentaBancaria (int numero, String titular, int saldoInicial) {

if (numero <= 0 || titular == null || titular == “”)

throw new IllegalArgumentException ( );

this.numero = numero;

this.titular = titular;

this.saldo = saldoInicial;

}

2c2009 22

A3F

Java: no todo es un objeto

Las instancias de tipos primitivos no son objetos

int, long, double, char, boolean

Y se manejan por valor (no por referencia)

Hay “encajonamiento” o “autoboxing”

Integer x = 4; // significa Integer x = new Integer(4);

Arreglos “primitivos” no son objetos

int [ ] v = new int [4];

Pero se manejan por referencia

Tamaño se establece en tiempo de ejecución

Una vez establecido, no puede variar

Hay chequeo de rangos

Tipo de los elementos definido estáticamente

2c2009 23

A3F

C#: casi todo es un objeto

Los tipos primitivos son tipos por valor

Pero hay encajonamiento

Los arreglos son instancias de System.Array

Hay muchos tipos por valor

Pero se manejan como clases

Y se pueden definir por el programador

Con algunas restricciones

2c2009 24

A3F

Delegación

Un objeto contiene referencias a otros objetos y les delega comportamiento

public class Segmento {

private Punto p1;

private Punto p2;

public double longitud ( ) {

return p1.distancia(p2);

}

...

}

2c2009 25

A3F

Herencia y lenguajes

En Java, para indicar herencia

public class Elipse extends Figura { ... }

En C# reemplazamos “extends” por “:”

public class Elipse : Figura { ... }

2c2009 26

A3F

Herencia, variables y objetos

“Casteo” hacia arriba automático

Elipse e = new Elipse();

Figura f = e; // válido y seguro

// e = f; inválido e inseguro

Otro caso

public void p (Figura x) { … }

// … luego será invocado:

p(e);// e es de tipo Elipse

Los llamamos “objetos polimorfos”

Parecen una cosa pero son otra

f es una Elipse aunque se la trate como Figura

Figura f = new Elipse ( ); // tipos distintos en la variable y el objeto !!

2c2009 27

A3F

Herencia y arreglos

O arreglos polimorfos

public Figura[ ] v = new Figura [3];

// luego…

v[0] = new Elipse ( );

v[1] = new Circulo ( );

v[2] = new TrianguloRectangulo ( );

Pero

Estamos perdiendo información del objeto

Cada v[i] sólo va a tener disponibles los atributos y métodos públicos de

Figura

Ya volveremos sobre esto

2c2009 28

A3F

Particularidades de Java y C#

Jerarquía de raíz única

Clase Object

Todo se puede transformar en un Object

Atributos y métodos comunes a todas las clases

Otras importantes consecuencias

Posibilidad de evitar la herencia

Declaramos la clase como “final”

Ejemplo: String

public final class String {...}

“sealed” en C#

2c2009 29

A3F

Constructores y herencia

Los constructores no se heredan

Cada clase debe tener el suyo

Receta

Llamar al constructor del ancestro al principio del constructor propio

// Java:

public Derivada( ) {

super(); ... }

// C#:

public Derivada( ) : base ( ) {

... }

Automático con constructores por defecto

2c2009 30

A3F

Redefinición en Java y C#

Los métodos privados no pueden ser redefinidos

Se estaría definiendo uno nuevo

Posibilidad de evitar la redefinición

Métodos “final”

public final void m() {...}

“sealed” en C#

No se puede redefinir un método haciéndolo más privado

Sobrecarga y redefinición

Redefinición se hace con la misma firma

Si no, es sobrecarga

2c2009 31

A3F

Clases abstractas

No tienen instancias

Caso de CuentaBancaria si implemento CajaAhorro

Pero pueden tener constructor

¡que no debe ser llamado nunca!

Generalizan estructura y comportamiento de varias clases

Caso del método depositar

O crean una familia

Se declara “abstract”

2c2009 32

A3F

Analizar

CuentaBancaria cb = new CuentaBancaria(…);

CuentaCorriente cc1 = new CuentaCorriente(…);

CuentaBancaria cc2 = new CuentaCorriente(…);

cb.extraer(200);

cc1.extraer(200);

cc2.extraer(200);

2c2009 33

A3F

Métodos virtuales (1)

2c2009 34

A3F

Métodos virtuales (2)

// llama al dibujar de Elipse:

unaElipse.mover();

// llama al dibujar de Triangulo:

unTriangulo.mover();

// llama al dibujar de la clase de cada figura:

v.dibujarTodas();

// porque dibujar es virtual

En Java y en Smalltalk la “virtualidad” se da por defecto

En C# y C++ debemos declarar métodos como “virtual”

Métodos de clase, privados y finales no son virtuales

2c2009 35

A3F

Métodos virtuales (3)

Los métodos virtuales agregan ineficiencias

Pero garantizan reutilización

Eliminar la “virtualidad” sólo si se demuestra que no se

van a redefinir y la presunta ineficiencia

Un método debe ser virtual sí o sí cuando se lo

redefinirá y es llamado desde:

Un método en una clase ancestro

Un método que delegue en el método en cuestión de la

clase ancestro

2c2009 36

A3F

Ejemplo estándar en C#

En Object

public virtual String ToString ( ) { … }

Console.WriteLine usa ToString()

Si quiero que un objeto sea imprimible, debo redefinir ToString:

En CuentaBancaria

public String ToString() {

return ( numero + titular + saldo.ToString() ); }

Luego...

CuentaBancaria cuenta = new CtaCte(12,”Juan”);

Console.WriteLine(cuenta);

2c2009 37

A3F

Métodos abstractos (1)

Nunca van a ser invocados

Caso del dibujar de Figura

Además, definen que toda instancia de una subclase

va a poder responder a ese mensaje

Aunque sin definir comportamiento, porque a nivel

de la clase madre no se puede prever

En lenguajes compilados, es también una necesidad

de compilación

2c2009 38

A3F

Métodos abstractos (2)

Corolarios

No tienen implementación

Deben redefinirse

Deben ser virtuales

En Java y C#:

public void abstract dibujar();

Si una clase tiene métodos abstractos debe ser

abstracta

2c2009 39

A3F

Clases internas

Pueden utilizar métodos y atributos privados de su clase

externa (sin relación de herencia)

Pueden ser descendientes de cualquier clase visible de la

clase externa

En una clase descendiente de la externa se puede declarar

una clase interna que descienda de la interna del ancestro

Se usan poco

2c2009 40

A3F

Clases dentro de métodos y anónimas (Java)

public class Externa {

//...

public void m ( ) {

class Interna extends Base {

// ...

}

Interna i = new Interna ( );

// ...

}

}

public class Externa {

//...

public Base m( ) {

// ...

return new Base( ) {

// declaración de la // clase anónima ...

}

}

}

2c2009 41

A3F

Manejo de problemas (v1)

public Fraccion (int numerador, int denominador) {

if (denominador == 0)

throw new ArgumentException( );

this.numerador = numerador;

this.denominador = denominador;

}

public Fraccion Dividir (Fraccion y) {

if (y.numerador == 0)

throw new DivideByZeroException( );

int numerador = this.numerador * y.denominador;

int denominador = this.denominador * y.numerador;

return new Fraccion(numerador, denominador);

}

2c2009 42

A3F

Manejo de problemas (v2)

public Fraccion (int numerador, int denominador) {

if (denominador == 0)

throw new FraccionInvalidaException ( );

this.numerador = numerador;

this.denominador = denominador;

}

public Fraccion Dividir (Fraccion y) {

if (y.numerador == 0)

throw new FraccionInvalidaException ( );

int numerador = this.numerador * y.denominador;

int denominador = this.denominador * y.numerador;

return new Fraccion(numerador, denominador);

}

2c2009 43

A3F

Clases de excepciones

¿Qué es FraccionInvalidaException?

Una clase de excepción

Debe derivar de Exception o una derivada

public class FraccionInvalidaException :

System.ApplicationException { }

Lo que se lanza es un objeto, instancia de esa clase

Las jerarquías influyen en la captura:

Se captura cualquier clase derivada

Ojo con el orden de captura

2c2009 44

A3F

Jerarquías de excepciones (Java)

En .NET todas las excepciones son “no chequeadas”

2c2009 45

A3F

Excepciones chequeadas (Java, 1)

Cláusula “throws” obligatoria

public Fraccion dividir (Fraccion y) throws FraccionInvalidaException {

if (y.numerador == 0)

throw new FraccionInvalidaException ( );

int numerador = this.numerador * y.denominador;

int denominador = this.denominador * y.numerador;

return new Fraccion(numerador, denominador);

}

A lo sumo se puede declarar un ancestro

En redefiniciones, mantener y no agregar

Para mantener el polimorfismo: muy molesto

2c2009 46

A3F

Excepciones chequeadas (Java, 2)

Obligación de capturar (I)

public Fraccion divisionMultiple ( Fraccion [ ] x, Fraccion [ ] y ) {

Fraccion suma = new Fraccion (0, 1);

try {

for (int i = 0; i < 10; i++) {

Fraccion d = x[i].dividir ( y [i] );

suma = suma.sumar(d);

}

} catch (FraccionInvalidaException e) {

System.err.println(“División por cero”);

return new Fraccion (0, 1);

}

return s;

}

2c2009 47

A3F

Excepciones chequeadas (Java, 3)

Obligación de capturar (II)

public Fraccion divisionMultiple ( Fraccion [ ] x, Fraccion [ ] y )

throws FraccionInvalidaException {

Fraccion suma = new Fraccion (0, 1);

for (int i = 0; i < 10; i++) {

Fraccion d = x[i].dividir( y[i] );

suma = suma.Sumar(d);

}

return s;

}

2c2009 48

A3F

Excepciones chequeadas (Java, 4)

Obligación de capturar (III)

public Fraccion divisionMultiple ( Fraccion [ ] x, Fraccion [ ] y) {

Fraccion suma = new Fraccion (0, 1);

try {

for (int i = 0; i < 10; i++) {

Fraccion d = x[i].dividir( y[i] );

suma = suma.sumar(d);

}

}catch (FraccionInvalidaException e) { }

return s;

}

2c2009 49

A3F

Lenguajes: enfoques

Excepciones chequeadas

Son más seguras

Molesta tener que capturarlas sí o sí

Limita la redefinición, al no poder agregar nuevas excepciones

Aunque cumple el principio de substitución

Microsoft diseñó .NET sin excepciones chequeadas

C++ tiene un enfoque mixto

Ojo: Java permite ambas

Aunque es una decisión de diseño

2c2009 50

A3F

Claves

Java y C# son lenguajes de tipos estáticos

La sintaxis deriva de C, pero la semántica no tanto

C# maneja “propiedades”, Java no

Más niveles de visibilidad que en Smalltalk

Herencia implica posibilidades de “casteo hacia arriba”

Polimorfismo por defecto en Java, no en C#

Excepciones chequeadas en Java, no en C#

Mejor soporte para clases y métodos abstractos que en Smalltalk

2c2009 51

A3F

Qué sigue

Interfaces, colecciones, genericidad

Primer parcial

Desarrollo de software y metodología