clase 21 clases - users.dcc.uchile.clnbaloian/cc1002... · clase 21 nelson baloian, josé a. pino....

23
CC 1002: Introducción a la Programación Clase 21 Nelson Baloian, José A. Pino

Upload: others

Post on 23-Jul-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

CC 1002: Introducción a la Programación

Clase 21

Nelson Baloian, José A. Pino

Page 2: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Definición de clase# Campos:

# numerador: int

# denominador: int

class FraccionV1:

# …

• Los campos de una clase son variables de estado que nos permiten almacenar información sobre los objetos de dicha clase.

• Los campos son indicados en la receta de diseño de la clase.

• Después de la especificación de “class”, se debe definir el método constructor de la clase.

Page 3: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Constructor

# Constructor

def __init__ (self, numerador=0, denominador=1):

# Inicializacion de campos

self.numerador = numerador

self.denominador = denominador

__init__ es el nombre del constructor. Sólo uno por clase.Primer parámetro: self: referencia al objeto que se está creando.Al crear un objeto, no se pone nada para el “self”:

f1 = FraccionV1(5, 9) # fracción 5/9

Parámetros “por defecto”:

f2 = FraccionV1() # fracción 0/1

Page 4: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Otro ejemplo

# Campos

# nombre: string

# tipo: string

# edad: int

class Mascota:

def __init__(self, nombre, tipo=“perro”, edad=0)

self.nombre = nombre

self.tipo = tipo

self.edad = edad

p = Mascota(“Fido”)

kitty = Mascota(“Silvestre”, “gato”, 2)

Page 5: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Método suma: dentro de la

clase FraccionV1# suma : fraccion -> fraccion

# devuelve la suma de la fraccion con otra fraccion

def suma (self , fraccion):

num = self.numerador*fraccion.denominador + \

fraccion.numerador*self.denominador

den = self.denominador*fraccion.denominador

return FraccionV1(num, den)

f1 = FraccionV1(1, 2)

f2 = FraccionV1(5, 6)

f3 = f1.suma(f2)

f1 corresponde a self

Page 6: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Métodos accesores y mutadores

• Accesores: no modifican campos del objeto. Ej.: suma

• Mutadores: modifican (o pueden modificar) los valores de los campos de la clase

• Indicar el efecto que puede tener un método mutador sobre los campos

• Ejemplo de método mutador: simplificar una fracción

• Al simplificar (eventualmente) debemos modificar numerador y denominador

• Supongamos que contamos con la función mcd(i1, i2)

Page 7: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Método simplificar (mutador)

# simplificar : None -> Fraccion

# efecto : simplifica la fraccion , puede modificar los

# valores de los campos numerador y denominador

def simplificar ( self ):

valor = mcd(self.numerador, self.denominador)

if valor > 1:

self.numerador = self.numerador/valor

self.denominador = self.denominador/valor

Por convención, a los métodos accesores se les pone nombre que comienza con get.

A los métodos mutadores, se les pone nombre que comienza con set.

Page 8: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Métodos accesores para la clase

FraccionV1Por convención, a los métodos accesores se les pone nombre que comienza con get.

A los métodos mutadores, se les pone nombre que comienza con set.

# getNumerador : None -> int

# devuelve el valor del campo numerador

def getNumerador(self):

return self.numerador

# getDenominador : None -> int

# devuelve el valor del campo denominador

def getDenominador(self):

return self.denominador

Page 9: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Métodos mutadores para la

clase FraccionV1

# setNumerador : int -> None

# efecto : modifica el valor del campo numerador

def setNumerador(self, numerador ):

self.numerador = numerador

# setDenominador : int -> None

# efecto : modifica el valor del campo denominador

def setDenominador(self, denominador ):

self.denominador = denominador

Page 10: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Receta de diseño

• Antes de definir la clase, se identifican los campos y tipos

• La definición de métodos sigue las reglas habituales de la receta de diseño

para funciones, pero los cuerpos de los métodos y los tests correspondientes

quedan pendientes.

• Una vez terminada la definición de métodos, fuera de la clase se implementan

los tests para todos los métodos.

• Se implementan los cuerpos de los métodos.

• Se ejecutan los tests.

• Se itera si es necesario (corrigiendo errores).

Page 11: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Clase FraccionV1 (P.1)

# Campos :

# numerador : int

# denominador : int

class FraccionV1 :

# Constructor

def __init__ (self, numerador = 0, denominador = 1):

# Inicializacion de campos

self.numerador = numerador

self.denominador = denominador

# getNumerador : None -> int

# devuelve el valor del campo numerador

def getNumerador ( self ):

return self.numerador

Page 12: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Clase FraccionV1 (P.2)

# getDenominador : None -> int

# devuelve el valor del campo denominador

def getDenominador (self):

return self.denominador

# setNumerador : int -> None

# efecto : modifica el valor del campo numerador

def setNumerador (self, numerador):

self.numerador = numerador

# setDenominador : int -> None

# efecto: modifica el valor del campo denominador

def setDenominador (self, denominador):

self.denominador = denominador

Page 13: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Clase FraccionV1 (P.3)

# toString : None -> str

# devuelve un string con la fraccion

def toString ( self ):

return str(self.numerador)+"/"+str(self.denominador)

# suma : fraccion -> fraccion

# devuelve la suma de la fraccion con otra fraccion

def suma (self, fraccion):

num = self.numerador*fraccion.denominador + \

fraccion.numerador*self.denominador

den = self.denominador*fraccion.denominador

return FraccionV1(num, den)

Page 14: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Clase FraccionV1 (P.4)

# mcd: int int -> int

# devuelve maximo comun divisor entre numeros x e y

# ejemplo : mcd (12 , 8) devuelve 4

global mcd

def mcd(x, y):

if x == y:

return x

elif x > y:

return mcd (x-y, y)

else :

return mcd (x, y-x)

# Test

assert mcd (12 , 8) == 4

Page 15: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Clase FraccionV1 (P.5)

# simplificar : None -> Fraccion

# efecto : simplifica la fraccion , puede modificar los

# valores de los campos numerador y denominador

def simplificar ( self ):

valor = mcd( self.numerador, self.denominador )

if valor > 1:

self.numerador = self.numerador / valor

self.denominador = self.denominador / valor

# Tests

f1 = FraccionV1(1, 2)

f2 = FraccionV1(5, 6)

# Test de accesores

assert f1.getNumerador() == 1

assert f2.getDenominador() == 6

Page 16: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Clase FraccionV1 (P.6)

# Test de mutadores

f2.setNumerador (3)

f2.setDenominador (4)

assert f2.getNumerador()==3 and f2.getDenominador()==4

# Test de metodo suma

# El siguiente test es incorrecto

# assert f1.suma(f2) == FraccionV1 (10 , 8)

# El siguiente test es correcto

f3 = f1.suma(f2)

assert f3.getNumerador()==10 and f3.getDenominador()==8

# Test de metodo toString

assert f3.toString() == "10/8"

# Test de metodo simplificar

f3.simplificar()

assert f3.getNumerador()==5 and f3.getDenominador()==4

Page 17: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

FraccionV2: una versión más

segura• Podemos crear una nueva clase FraccionV2 que no tiene métodos

mutadores.

• Para ello, creamos nuevos métodos accesadores, en donde el resultado se

almacena en un nuevo objeto de la misma clase (y/o se eliminan métodos

mutadores).

• Además, para evitar que un usuario fuera de la clase pueda modificar los

campos de un objeto, en Python se pueden definir con nombres que

comiencen con los caracteres __ (dos caracteres subrayado), y esto los

hace inaccesibles fuera de la clase.

• Si uno intenta modificar un campo que comienza con __, Python arroja el

error AttributeError.

Page 18: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Clase FraccionV2 (P.1)

# Campos :

# numerador : int

# denominador : int

class FraccionV2 :

# Constructor

def __init__(self,numerador=0,denominador=1):

# Inicializacion de campos

# campos invisibles al usuario

self.__numerador = numerador

self.__denominador = denominador

# getNumerador : None -> int

# devuelve el valor del campo numerador

def getNumerador ( self ):

return self.__numerador

Page 19: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Clase FraccionV2 (P.2)

# getDenominador : None -> int

# devuelve el valor del campo denominador

def getDenominador ( self ):

return self.__denominador

# toString : None -> str

# devuelve un string con la fraccion

def toString ( self ):

return str(self.__numerador)+"/"+str(self.__denominador)

# suma : Fraccion -> Fraccion

# devuelve la suma de la fraccion con otra fraccion

def suma(self, fraccion ):

num = self.__numerador*fraccion.__denominador+ \

fraccion.__numerador*self.__denominador

den = self.__denominador*fraccion.__denominador

return FraccionV2(num, den)

Page 20: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Clase FraccionV2 (P.3)

# mcd: int int -> int

# devuelve el maximo comun divisor entre dos numeros x e y

# ejemplo : mcd (12 , 8) devuelve 4

global mcd

def mcd(x, y):

if x == y:

return x

elif x > y:

return mcd (x-y, y)

else :

return mcd (x, y-x)

# Test

assert mcd(12, 8) == 4

Page 21: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Clase FraccionV2 (P.4)

# simplificar : None -> Fraccion

# devuelve la fraccion simplificada

def simplificar ( self ):

valor = mcd(self.__numerador , self.__denominador )

num = self.__numerador / valor

den = self.__denominador / valor

return FraccionV2(num, den )

# Tests

f1 = FraccionV2 (1, 2)

f2 = FraccionV2 (3, 4)

# Test de accesores

assert f1.getNumerador() == 1

assert f2.getDenominador() == 4

#

Page 22: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

Clase FraccionV2 (P.5)

# Test de metodo suma

f3 = f1.suma(f2)

assert f3.getNumerador()==10 and f3.getDenominador()==8

# Test de metodo toString

assert f3.toString() == "10/8"

# Test de metodo simplificar

f4 = f3.simplificar()

assert f4.getNumerador()==5 and f4.getDenominador()==4

Page 23: Clase 21 Clases - users.dcc.uchile.clnbaloian/cc1002... · Clase 21 Nelson Baloian, José A. Pino. Definición de clase ... # denominador: int class FraccionV1: # … • Los campos

(martes)

Leer capítulo 16 del apunte

Para la próxima clase