Clases y Objetos

20
Clases y Objetos 1

Transcript of Clases y Objetos

Page 1: Clases y Objetos

Clases y Objetos

1

Page 2: Clases y Objetos

Creación de objetos JavaScript no es un lenguaje orientado a objetos en

sentido estricto (aunque si basado en objetos)

Un objeto en JavaScript es realmente una colección de propiedades. Las propiedades pueden tener forma de datos, tipos, funciones (métodos) o incluso otros objetos.

Un objeto de JavaScript es similar a un array de valores, donde cada uno de los cuales está asociado a una propiedad (un tipo de datos, método u objeto).

Un método puede ser una propiedad de un objeto.

Una función contenida en un objeto se conoce como un método. Los métodos no son diferentes de las funciones vistas anteriormente, excepto que han sido diseñados para ser utilizados en el contexto de un objeto, y por lo tanto, tendrán acceso a las propiedades de ese objeto. Esta conexión entre propiedades y métodos es uno de los ejes centrales de la orientación a objetos.

2

Page 3: Clases y Objetos

Constructores Los objetos se crean empleando una función especial denominada constructor,

determinada por el nombre del objeto. Ejemplo de una función constructor:

function Coche( ){

// propiedades y métodos

}

class persona { //ES6

constructor(nombre,apellidos,edad = 0){

this._nombre =nombre;

this._apellidos = apellidos;

this._edad = edad;

}

}

Un constructor como un molde o plantilla, que será utilizada para crear objetos.

Por convención, los nombres de los constructores se ponen generalmente con las iniciales de cada palabra en mayúscula y cuando creamos un objeto con ese constructor (instancia de ese objeto), lo haremos empleando minúsculas al principio. Por ejemplo:

var unCoche = new Coche();

La palabra reservada new se emplea para crear objetos en JavaScript. Al crear la variable unCoche de esta forma, técnicamente podríamos decir que hemos creado una instancia de la clase Coche, o que hemos instanciado el objeto Coche, o que hemos creado un objeto Coche, etc.

3

Page 4: Clases y Objetos

Definición de propiedades Las propiedades para un objeto se crearán dentro del constructor

empleando la palabra reservada this. function Coche(){

// Propiedades

this.marca = "Audi A6";

this.combustible = "diesel";

this.cantidad = 0; // Cantidad de combustible en el depósito.

}

La palabra reservada this, se utiliza para hacer referencia al

objeto actual, que en este caso será el objeto que está siendo

creado por el constructor.

this, permite crear nuevas propiedades para el objeto.

El único problema del ejemplo anterior es que todos los coches

que hagamos del tipo Coche serán siempre Audi A6, diésel y sin

combustible en el depósito.var cocheDeMartin = new Coche();

var cocheDeSilvia = new Coche();

4

Page 5: Clases y Objetos

Definición de propiedades Los valores de las propiedades de los objetos deberían ser configurables en el

momento de la creación del objeto. Para ello, usamos los argumentos o parámetros en el constructor.

El siguiente ejemplo es una variación del constructor Coche para que permita crear cualquier tipo de coche.

function Coche(propietario,marca,combustible,litros){

this.propietario = propietario;

this.marca = marca;

this.combustible = combustible;

this.cantidad = litros;

}

var coche1 = new Coche("Martín","Volkswagen Golf","gasolina",45);

var coche2 = new Coche("Silvia","Mercedes SLK","diesel",55);

Una vez creados dos objetos de tipo Coche, podemos consultar y/o modificar sus propiedades:

document.write(coche1.propietario+" tiene un "+coche1.marca+"<br/>");

document.write(coche2.propietario+" tiene un "+coche2.marca);

coche1.marca = "BMW X5";

coche1.combustible = "diesel";

document.write(coche1.propietario+" tiene ahora un "+coche1.marca+

"<br/>");

5

Page 6: Clases y Objetos

Definición de métodos Esta operación se puede realizar de dos formas:

◦ Usando una función anónima (sin nombre) declarada dentro del constructor.

◦ Asignando como valor a una de las propiedades del constructor una función externa.

Empleo de una función anónimafunction Coche(propietario,marca,combustible){

this.propietario = propietario;

this.marca = marca;

this.combustible = combustible;

this.cantidad=0; //todos los coches se inicializan con 0 litros en

el depósito

this.rellenarDeposito = function (litros){ /función anónima

this.cantidad=litros;

};

}

Las funciones anónimas llevan un punto y coma después de la llave de cierre.

Esto se debe a que terminamos la definición del valor asignado a una propiedad.

6

Page 7: Clases y Objetos

Definición de métodosfunction rellenarDeposito(litros){

this.cantidad = litros;

}

function Coche(propietario,marca,combustible){

this.propietario = propietario;

this.marca = marca;

this.combustible = combustible;

this.cantidad=0;

this.rellenarDeposito = rellenarDeposito; //función externa

}

//En ambos casos el método o función se usa de la misma manera

var coche1 = new Coche("Martín","Volkswagen Golf","gasolina");

coche1.rellenardeposito(45); //rellenamos el depósito con 45 litros

La segunda forma define el método rellenarDeposito a nivel global. Ésta no es la

mejor práctica en la programación orientada a objetos. Se recomienda el uso de la

primera forma, ya que es una mejor aproximación a la orientación a objetos donde los

métodos definidos están dentro del constructor aportan mayor privacidad y seguridad

al objeto.

Siguiendo un poco con el tema de las mejores prácticas, podemos decir que el acceso a

las propiedades que hacíamos en el subapartado anterior no es el más adecuado en la

orientación a objetos, ya que realmente se suele acceder a estas propiedades a través

de los métodos definidos en el propio objeto. Es lo que se conoce como

Encapsulamiento en la Programación Orientada a Objetos. 7

Page 8: Clases y Objetos

Definición de métodosfunction Coche(propietario,marca,combustible){

this.propietario = propietario;

this.marca = marca;

this.combustible = combustible;

this.cantidad=0; //todos los coches se inicializan con 0 litros en el depósito

this.imprimeMarca = function(){

return this.marca;

};

this.imprimePropietario = function(){

return this.propietario;

};

this.cambiarCoche = function(marca,combustible) {

this.marca = marca;

this.combustible = combustible;

};

this.venderCoche = function(nuevoPropietario) {

this.propietario = nuevoPropietario;

};

}

var c = new Coche("Martín","Volkswagen Golf","gasolina");

document.write(c.imprimePropietario()+" conduce un "+c.imprimeMarca()+"<br />");

c.cambiarCoche("Toyota","Diesel");

document.write(c.imprimePropietario()+" conduce ahora un "+c.imprimeMarca()+"<br />");

c.venderCoche("Enrique");

document.write(c.imprimePropietario()+" es ahora el nuevo propietario del "+c.imprimeMarca()+"<br />");

8

Page 9: Clases y Objetos

Definición de objetos literales Los literales de objeto se utilizan para almacenar

información en parejas nombre-valor.

Un literal de objeto se define mediante llaves ({ y }) dentro las cuales podemos colocar cualquier número de parejas nombre-valor, definida mediante una cadena, un símbolo de dos puntos y el valor. Cada pareja nombre-valor deben estar separadas por coma.

Ejemplos de definición de objetos literales://Forma 1

avion = { "marca":"Boeing","modelo":"747","pasajeros":450 };

//Forma 2

var avion = new Object();

avion.marca = "Boeing";

avion.modelo = "747";

avion.pasajeros = 450;

9

Page 10: Clases y Objetos

Definición de objetos literales Para referirnos desde JavaScript a una propiedad del objeto

avion podríamos hacerlo, también, de dos formas://Forma 1 (a través de su propiedad)

document.write(avion.marca);

//Forma 2

document.write(avion["modelo"]); //usando el nombre de la propiedad como índice

Incluso podríamos tener un conjunto de objetos literales simplemente creando un array que contenga en cada posición una definición de un objeto literal. El siguiente ejemplo es una muestra de ello:

var datos=[

{"id":"10","nombrecentro":"IES As Fontiñas","localidad":"Santiago","provincia":"ACoruña"},

{"id":"9","nombrecentro":"IES A Carballeira","localidad":"Ourense","provincia":"Ourense"},

{"id":"4","nombrecentro":"IES de Teis","localidad":"Vigo","provincia":"Pontevedra"},

{"id":“27","nombrecentro":"IES A Pinguela","localidad":“Monforte","provincia":“Lugo"}];

for (var i=0; i< datos.length; i++){

document.write("El centro "+datos[i].nombrecentro+" con ID nº "+datos[i].id + " está en ");

document.write(datos[i].localidad+" en la provincia de " +datos[i].provincia+"<br/>");

}

10

Page 11: Clases y Objetos

Clases JS Declaración. Se emplea la palabra reservada “class”

class persona {

//aquí se definen el constructor, métodos get, set, etc..

}

El constructor es un método especial que inicializa una instancia de la clase. En JavaScript sólo puede haber un constructor (no existe el concepto de sobrecarga como en otros lenguajes de programación). Ejemplo:

class persona {

constructor(nombre,apellidos,edad = 0){

this._nombre =nombre;

this._apellidos = apellidos;

this._edad = edad;

}

}

El constructor anterior recibe tres argumentos de entrada. Si no se especifica la edad, esta tomará el valor 0.

También se puede usar la palabra reservada super para llamar al constructor de la clase padre.

this hace referencia al propietario de la función o propiedad que está invocándose.

11

Page 12: Clases y Objetos

Clases: getters y setters Los métodos de acceso denominados ‘getters‘ y ‘setters‘ se utilizan para obtener y asignar valores a los

atributos de nuestros objetos respectivamente.

La definición de métodos ahora es más sencilla, ya no hay que escribir la palabra function, solo el

nombre del método y su implementación:

Get: Es una propiedad que nos permite ejecutar una función la cual es llamada cuando la propiedad es

requerida. No recibe parámetros.

Set: Es una propiedad que permite ejecutar una función la cual se ejecutará para asignar un valor. Sólo

recibe un parámetro el cual es el valor que será asignado.

class Persona {

constructor(nombre,apellidos,edad = 0){

this._nombre = nombre;

this._apellidos = apellidos;

this._edad = edad;

}

get nombre(){

return this._nombre

}

set nombre(nom){

this._nombre = nom;

}

}

Es conveniente emplear nombres diferentes para las propiedades y los métodos, ya que nos evita

problemas de referencias circulares:

Acceder a un ‘setter‘ que modifica una propiedad con su mismo nombre, crea una

llamada de función recursiva infinita.

Completa la clase persona con los

getters y setters que faltan

12

Page 13: Clases y Objetos

class Persona {

constructor(nombre,apellidos,edad = 0){

this._nombre = nombre;

this._apellidos = apellidos;

this._edad = edad;

}

//getters

get nombre(){

return this._nombre

}

get apellidos(){

return this._apellidos

}

get edad(){

return this._edad

}

//setters

set nombre(nom){

this._nombre = nom;

}

set apellidos (ape){

this._apellidos = ape;

}

set edad(ed){

this._edad = ed;

}

}

13

Page 14: Clases y Objetos

Clases: crear una instancia Se emplea el operador new. En el ejemplo se crea el objeto

pers, con los argumentos de entrada juan, perez y 34:var pers = new Persona("juan","perez",34);

pers.apellidos //"perez“

pers.nombre() //"juan“

pers.edad() //34

Pers.edad = 37;

Alert (“Ahora la edad es: “+ pers.edad);

Para acceder a los atributos del objeto, empleamos los métodos getters, en lugar de acceder directamente al atributo:

Pers._edad (esto es posible, ya que los atributos son públicos) pero es preferible utilizar el método.

Para más información consulta: http://www.etnassoft.com/2016/12/02/introduccion-a-la-poo-en-javascript-moderno-las-nuevas-clases-en-es6/

14

Page 15: Clases y Objetos

Clases: Métodos estáticos Los métodos estáticos son aquellos que son invocados sin necesidad de

instanciar la clase.

Suelen emplearse para realizar operaciones comunes a todos los objetos de la clase. No afectan a los estados de los mismos (a los valores de sus variables de instancia).

class Persona {

constructor(nombre,apellidos,edad = 0){

this._nombre = nombre;

this._apellidos = apellidos;

this._edad = edad;

}

get nombre(){

return this._nombre

}

set nombreP(nom){

this._nombre = nom;

}

static imprimirNombreApellidos(nom,ape){

console.log(nom+ “ “+ ape);

}

}

Persona.imprimirNombreApellidos(“Juan”,”Pérez”);

15

Page 16: Clases y Objetos

Herencia Se emplea la clausula extends (al igual que en Java)class Persona {

constructor(nombre,apellidos,edad = 0){

this._nombre = nombre;

this._apellidos = apellidos;

this._edad = edad;

}

//getters

get nombre(){

return this._nombre

}

//resto de métodos de la clase …

}

class Alumno extends Persona {

constructor(nombre, apellidos, edad) {

super(nombre, apellidos, edad);

}

}

Var alum = new Alumno ("pepe", "garcia", 30 );

alert (“alumno: ”+ alum.nombre()+ “ tiene “+ alum.edad + “ años”);

Utilizamos super, para invocar al constructor de la clase madre.

16

Page 17: Clases y Objetos

Herencia Veamos otro ejemplo donde se emplea super() para invocar constructor de la clase de

la cual se hereda. En este caso el constructor de la clase heredada necesita 3 parámetros:

class Punto {

constructor(x, y) {

this.x = x;

this.y = y;

}

toString() {

return '(' + this.x + ', ' + this.y + ')';

}

}

class PuntoDeColor extends Punto {

constructor(x, y, color) { //constructor

super(x, y);

this.color = color;

}

toString() {//método

return super.toString() + ' in ' + this.color;

}

}

Además también se invoca al método .toString() de la clase madre, empleando super.toString().

17

Page 18: Clases y Objetos

Uso del operador de propagación

con objetos (spread operator)

Sea el siguiente código:

const usuario = {“nombre”:”juan”,”edad”:23}

let usuario2 = usuario;

En esta asignación se almacena una referencia al objeto

usuario2.nombre=“ana”;

//usuario.nombre y usuario2.nombre es “ana”

Para evitar esto, emplear:

usuario2 = {…usuario}

18

Page 19: Clases y Objetos

Uso del operador de propagación

con objetos (spread operator)

let contacto = { “teléfono”:666777888,”mail”:’[email protected]’}

let user = {…usuario,… contacto}

let user2 = {…usuario,…contacto,mail:’[email protected]’}

19

Page 20: Clases y Objetos

Desestructuración de objetos

Desempaquetar las propiedades de un objeto

const usuario = {'nombre':'juan','edad':23}

const {nombre, edad} = usuario;

//nombre es "juan“ y edad es 23

Desestructuración en los argumentos de una función

function imprimirUsuario({nombre}){

console.log(nombre);

}

imprimirUsuario(usuario)

20