clases y objetos
TRANSCRIPT
Clases y Objetos
1
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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