You are on page 1of 9

DESARROLLO DE SOFTWARE VI CICLO

JVASCRIPT POO

LABORATORIO N 15.O1

La programacin orientada a objetos siempre ha sido una asignatura


pendiente en JavaScript. Si bien es cierto que este leguaje incorpora, desde
hace mucho tiempo, clases propias como Array, Date, JSON o Math, por
ejemplo, con sus propiedades o mtodos, carecamos de la posibilidad de
crear nuestras propias clases y utilizar una sintaxis especfica de POO como
tenemos en otros lenguajes. S. Es cierto que podemos crear arreglos de
variables y gestionarlas, hasta cierto punto, como si fueran propiedades de
un objeto

JS6 soluciona esa carencia, permitindonos crear clases, emplear herencia,


y disponer de las funcionalidades de la POO. Es cierto que el mecanismo
proporcionado an podra mejorarse y, seguramente, evolucionar en un
futuro prximo. No obstante, tal cmo est ya constituye un paso de gigante que no podemos
dejar de analizar en esta serie de artculos.

Este artculo est orientado a la POO en JavaScript 6. No es un manual de POO y, aunque


repasamos algunos conceptos generales, entiendo que ests familiarizado con las generalidades
de la POO, aunque la hayas usado en otros lenguajes.

CREAR UNA CLASE

Vamos a ver como creamos una clase en JS6, con su estructura bsica. Empecemos con este
cdigo:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS 6</title>
</head>
<body>
<div id="capaDeResultados"></div>
<script language="javascript">
class Personal {
constructor (nombre, apellidos){
this.nombre = nombre;
this.apellidos = apellidos;
}
}
var empleado_1 = new Personal("Pedro", "Garca Muoz");
document.getElementById("capaDeResultados").innerHTML += "Nombre: " +
empleado_1.nombre + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Apellidos: " +
empleado_1.apellidos + "<br>";
</script>

INSTRUCTOR: CLAROS VASQUEZ Carlos Orlando cclaros@senati.pe Pg. N 01


DESARROLLO DE SOFTWARE VI CICLO

</body>
</html>

El resultado que vemos en la pgina es el siguiente:


Nombre: Pedro
Apellidos: Garca Muoz

Analicemos lo que tenemos. Las clases, al igual que en otros lenguajes, se decalran con la palabra
reservada class, seguida del nombre de la clase que vamos a crear. La palabra class no exista
hasta ahora en JavaScript, por lo que nos estaba vedado crear estas estructuras. Lo vemos en la
lnea 10. Como puedes ver, todo el cdigo de la clase se acota con llaves.

En el interior de la clase se crean los mtodos que se vayan a emplear. La forma de crear un
mtodo es similar a la declaracin de funciones de usuario, pero sin emplear la palabra function.
Lo normal es empezar la definicin de la clase creando el mtodo constructor, que se denomina,
precisamente, as: constructor(). El mtodo constructor no necesita ser invocado desde ninguna
parte del cdigo. Cuando se instancia un objeto de la clase, el mtodo constructor se ejecuta
automticamente. El mtodo constructor no es obligatorio, pero s muy recomendable por
razones organizativas y de claridad del cdigo. En este sentido, se ha seguido la misma forma de
trabajo que en otros lenguajes.

Observa en el ejemplo que el constructor recibe dos argumentos, que asigna a dos variables de
instancia (de la instancia que se est creando en cada momento). Para ello emplea el comodn
this que, como sin duda ya sabes, se refiere siempre al objeto en curso. Ves la forma en que acta
entre las lneas 11 y 14 del cdigo.

La forma de crear un nuevo objeto de una clase es la misma que en cualquier lenguaje que use el
paradigma POO: mediante el operador new, seguido del nombre de la clase y un juego de
parntesis. Entre estos parntesis se incluyen los argumentos que le queramos pasar al
constructor, ya que, como hemos comentado, este se ejecuta automticamente al instanciar la
clase en un objeto. Lo vemos en la lnea 16.

Una vez creado un objeto de una clase, y establecidas sus propiedades, bien sea en el constructor,
mediante otro mtodo o, incluso, directamente en cdigo, podemos leer el valor de las mismas
mediante la sintaxis tpica de objeto.propiedad, como vemos en las lneas 17 y 18 del cdigo.

PRIMERAS LIMITACIONES

Aunque todava no hemos tenido ocasin de comprobarlo, te adelanto tres limitaciones que
tienen las clases en JS6 y que muchos esperamos que se solucionen en prximas revisiones del
estndar.

En primer lugar, tu no puedes definir o usar variables fuera de los mtodos. En otros leguajes
(cmo PHP, por ejemplo, sin ir ms lejos) es habitual encontrar una definicin de clase con un
esquema similar al siguiente:

class MiClase(){
variable_1 = "";

INSTRUCTOR: CLAROS VASQUEZ Carlos Orlando cclaros@senati.pe Pg. N 02


DESARROLLO DE SOFTWARE VI CICLO

variable_2 = 0;
variable_3 = true;
variable_4 = "Valor inicial";
metodo1(){
...
}
}

Esta declaracin previa de las variables que se usarn en el objeto, antes de empezar a declarar
los mtodos, es muy til, a efectos organizativos. Cuando tu calse emplea una gran cantidad de
variables, poder declararlas antes de empezar conlos mtodos es realmente prctico. JavaScript
lanza un error si intentas hacer algo as.

La segunda limitacin, consecuencia directa de la primera, es que slo puedes tener variables de
objeto, pero no de clase. La POO en JS6 no contempla la declaracin y uso de variables estticas
(aunque s de mtodos estticos, como veremos enseguida).

Tambin nos encontramos con otra limitacin importante (y esta s es realmente grave). No es
posible declarar propiedades o mtodos privados. Todos los elementos que componen un objeto
son, ineludiblemente, pblicos. Si ests familiarizado con la programacin orientada a objetos,
esto te parecer imperdonable pero, al menos por ahora, es as.

OTRO EJEMPLO

Ampliando el cdigo anterior, podemos tener un ejemplo como el siguiente:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS 6</title>
</head>
<body>
<div id="capaDeResultados"></div>
<script language="javascript">
class Personal {
constructor (nombre, apellidos){
this.nombre = nombre;
this.apellidos = apellidos;
}
establecerSalario (salario){
this.salarioBruto = salario;
var retencion = 18.7;
var descuento = (salario * retencion) / 100;
this.salarioNeto = salario - descuento;
}
}
var empleado_1 = new Personal("Pedro", "Garca Muoz");
empleado_1.establecerSalario(1000);

INSTRUCTOR: CLAROS VASQUEZ Carlos Orlando cclaros@senati.pe Pg. N 03


DESARROLLO DE SOFTWARE VI CICLO

document.getElementById("capaDeResultados").innerHTML += "Nombre: " +


empleado_1.nombre + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Apellidos: " +
empleado_1.apellidos + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Salario bruto: "
+ empleado_1.salarioBruto + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Salario neto: "
+ empleado_1.salarioNeto + "<br>";
</script>
</body>
</html>

El resultado en la pgina es el siguiente:


Nombre: Pedro
Apellidos: Garca Muoz
Salario bruto: 1000
Salario neto: 813

Observa el mtodo establecerSalario(), definido entre las lneas 15 y 20. Cmo ves, dentro de un
mtodo si se pueden declarar variables que no son propias del objeto, como hemos hecho en las
lneas 17 y 18. Sin embargo, esas variables pueden emplearse, exclusivamente, cmo las hemos
usado aqu, para el desarrollo del mtodo. No son variables de clase, ni viven fuera del mtodo
en el que han sido declaradas. Y, cmo hemos comentado antes, tampoco nos es posible declarar
una variable dentro de la clase fuera de los mtodos.

MTODOS ESTTICOS

La seccin anterior nos ha servido para hacernos una idea general del uso de clases en JS6, as
como tambin de las limitaciones que, desafortunadamente, an presentan. Al menos, ya que no
podemos declarar variables estticas, o variables y mtodos privados, si se nos permite crear
mtodos estticos (de clase). Observa el siguiente listado:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS 6</title>
</head>
<body>
<div id="capaDeResultados"></div>
<script language="javascript">
class Personal {
constructor (nombre, apellidos){
this.nombre = nombre;
this.apellidos = apellidos;
}
establecerSalario (salario){
this.salarioBruto = salario;
var retencion = 18.7;

INSTRUCTOR: CLAROS VASQUEZ Carlos Orlando cclaros@senati.pe Pg. N 04


DESARROLLO DE SOFTWARE VI CICLO

var descuento = (salario * retencion) / 100;


this.salarioNeto = salario - descuento;
}
static sumarSalarios(...Empleados){
var totalSalario = 0;
for (var emp of Empleados) totalSalario += emp.salarioBruto;
return totalSalario;
}
}
var empleado_1 = new Personal("Pedro", "Garca Muoz");
empleado_1.establecerSalario(1000);
var empleado_2 = new Personal("Carmen", "Martn Domnguez");
empleado_2.establecerSalario(1200);
document.getElementById("capaDeResultados").innerHTML += "PRIMER
EMPLEADO<br>";
document.getElementById("capaDeResultados").innerHTML += "Nombre: " +
empleado_1.nombre + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Apellidos: " +
empleado_1.apellidos + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Salario bruto: "
+ empleado_1.salarioBruto + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Salario neto: "
+ empleado_1.salarioNeto + "<br>";
document.getElementById("capaDeResultados").innerHTML +=
"=================================<br>";
document.getElementById("capaDeResultados").innerHTML += "SEGUNDO
EMPLEADO<br>";
document.getElementById("capaDeResultados").innerHTML += "Nombre: " +
empleado_2.nombre + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Apellidos: " +
empleado_2.apellidos + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Salario bruto: "
+ empleado_2.salarioBruto + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Salario neto: "
+ empleado_2.salarioNeto + "<br>";
document.getElementById("capaDeResultados").innerHTML +=
"=================================<br>";
document.getElementById("capaDeResultados").innerHTML += "TOTAL DE
SALARIOS: " + Personal.sumarSalarios(empleado_1, empleado_2) + "<br>";
</script>
</body>
</html>

El resultado en la pgina es el siguiente:


PRIMER EMPLEADO
Nombre: Pedro
Apellidos: Garca Muoz
Salario bruto: 1000
Salario neto: 813

INSTRUCTOR: CLAROS VASQUEZ Carlos Orlando cclaros@senati.pe Pg. N 05


DESARROLLO DE SOFTWARE VI CICLO

=================================
SEGUNDO EMPLEADO
Nombre: Carmen
Apellidos: Martn Domnguez
Salario bruto: 1200
Salario neto: 975.6
=================================
TOTAL DE SALARIOS: 2200

Observa el mtodo definido entre las lneas 21 y 25. Cmo ves, ha sido declarado con la palabra
reservada static, lo que le convierte en un mtodo de clase. Cmo ves, lo que hacemos es pasarle
un arreglo con los objetos que tenemos definidos de la clase Personal (empleado_1 y empleado_2,
en nuestro ejemplo). La forma de pasarle estos datos la conocemos ya por haberla visto,
previamente, en esta serie. Dentro del mtodo, sumamos los salarios brutos de los empleados y
los devolvemos.

Observa en la lnea 43 cmo invocamos a un mtodo esttico, segn el esquema clase.metodo():

document.getElementById("capaDeResultados").innerHTML += "TOTAL DE SALARIOS: " +


Personal.sumarSalarios(empleado_1, empleado_2) + "<br>";

Si ests familiarizado con la POO en otros lenguajes podras estar espeando que la invocacin
fuese del tipo clase::metodo(), pero esta sintaxis no funciona en JavaScript.

HERENCIA

La herencia es un concepto fundamental de JavaScript. Permite que una clase, que llamaremos
derivada, sea creada extendiendo otra clase, a la que llamaremos padre. De este modo, la clase
derivada tendr todas las propiedades y mtodos de la clase padre, adems de implementar los
suyos propios. Observa el siguiente cdigo de ejemplo:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS 6</title>
</head>
<body>
<div id="capaDeResultados"></div>
<script language="javascript">
class Personal {
constructor (nombre, apellidos){
this.nombre = nombre;
this.apellidos = apellidos;
}
establecerSalario (salario){
this.salarioBruto = salario;
var retencion = 18.7;
var descuento = (salario * retencion) / 100;

INSTRUCTOR: CLAROS VASQUEZ Carlos Orlando cclaros@senati.pe Pg. N 06


DESARROLLO DE SOFTWARE VI CICLO

this.salarioNeto = salario - descuento;


}
static sumarSalarios(...Empleados){
var totalSalario = 0;
for (var emp of Empleados) totalSalario += emp.salarioBruto;
return totalSalario;
}
}

class Empleados extends Personal {


constructor (nombre, apellidos){
super(nombre, apellidos);
}
establecerDepartamento(dpto){
this.departamento = dpto;
}
}
var empleado_1 = new Empleados ("Pedro", "Garca Muoz");
empleado_1.establecerSalario(1000);
empleado_1.establecerDepartamento("Mantenimiento");
var empleado_2 = new Empleados ("Carmen", "Martn Domnguez");
empleado_2.establecerSalario(1200);
empleado_2.establecerDepartamento("Seguridad");

document.getElementById("capaDeResultados").innerHTML += "PRIMER
EMPLEADO<br>";
document.getElementById("capaDeResultados").innerHTML += "Nombre: " +
empleado_1.nombre + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Apellidos: " +
empleado_1.apellidos + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Salario bruto: "
+ empleado_1.salarioBruto + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Salario neto: "
+ empleado_1.salarioNeto + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Departamento:
" + empleado_1.departamento + "<br>";
document.getElementById("capaDeResultados").innerHTML +=
"=================================<br>";
document.getElementById("capaDeResultados").innerHTML += "SEGUNDO
EMPLEADO<br>";
document.getElementById("capaDeResultados").innerHTML += "Nombre: " +
empleado_2.nombre + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Apellidos: " +
empleado_2.apellidos + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Salario bruto: "
+ empleado_2.salarioBruto + "<br>";
document.getElementById("capaDeResultados").innerHTML += "Salario neto: "
+ empleado_2.salarioNeto + "<br>";

INSTRUCTOR: CLAROS VASQUEZ Carlos Orlando cclaros@senati.pe Pg. N 07


DESARROLLO DE SOFTWARE VI CICLO

document.getElementById("capaDeResultados").innerHTML += "Departamento:
" + empleado_2.departamento + "<br>";
document.getElementById("capaDeResultados").innerHTML +=
"=================================<br>";
document.getElementById("capaDeResultados").innerHTML += "TOTAL DE
SALARIOS: " + Personal.sumarSalarios(empleado_1, empleado_2) + "<br>";
</script>
</body>
</html>

Al cargar el documento ves en tu navegador lo siguiente:


PRIMER EMPLEADO
Nombre: Pedro
Apellidos: Garca Muoz
Salario bruto: 1000
Salario neto: 813
Departamento: Mantenimiento
=================================
SEGUNDO EMPLEADO
Nombre: Carmen
Apellidos: Martn Domnguez
Salario bruto: 1200
Salario neto: 975.6
Departamento: Seguridad
=================================
TOTAL DE SALARIOS: 2200

Empecemos a ver cmo funciona. En primer lugar fjate en cmo se ha creado la clase Empleados
en la lnea 28. Con la palabra reservada extends le estamos diciendo a JavaScript que esta clase
que estamos creando (Empleados) deriva de Personal. As pues, Personal es la clase padre y
Empleados es la clase derivada.

Esto quiere decir que Empleados tiene todos los mtodos de Personal. Eso es, exactamente, la
herencia. Adems, por supuesto, la clase derivada puede implementar sus propios mtodos.

Un caso que requiere especial atencin es el del constructor de la clase derivada. Fjate que recibe
dos parmetros (nombre y apellidos). Dentro del constructor encontramos la palabra reservada
super, escrita como una funcin, es decir, seguida de unos parntesis entre los que se pueden
encerrar argumentos. Cuando en el constructor se invoca a super lo que est haciendo es llamar,
a su vez, al constructor de la clase padre, pasndole, en este caso, los dos parmetros recibidos
(nombre y apellidos). As es realmente el constructor de la clase padre el que se ejecuta. Por
supuesto, el constructor de la clase derivada podra tener ms instrucciones que no figuren en el
constructor de la clase padre. Supongamos que tenemos el constructor de la clase derivada
(Empleados), escrito as:

constructor (nombre, apellidos, nacionalidad){


super (nombre, apellidos);
this.nacionalidad = nacionalidad;
}

INSTRUCTOR: CLAROS VASQUEZ Carlos Orlando cclaros@senati.pe Pg. N 08


DESARROLLO DE SOFTWARE VI CICLO

Cuando creas un objeto de la clase Empleados le pasas tres argumentos: nombre, apellidos y
nacionalidad. El constructor de Empleados, que es la clase derivada, invoca al constructor de la
clase padre, pasandole el nombre y apellidos, con lo que el objeto creado ya tiene estas dos
variables, porque as lo ha hecho el constructor de la clase padre. A continuacin, el constructor
de la clase derivada contina ejecutndose, y crea otra variable al objeto con la nacionalidad. Este
tercer argumento no ha sido pasado a super, porque el constructor de la clase padre no lo recibe
ni gestiona en modo alguno.

Observa que en este ltimo cdigo hemos creado los dos empleados de la clase Empleados (la
derivada), no de la clase Personal (la padre). Como la clase Empleados incorpora un mtodo
nuevo, al que hemos llamado establecerDepartamento(), lo hemos podido usar en los dos objetos.
Si alguno de los objetos (empleado_1 o empleado_2) se hubiera instanciado de la clase padre
(Personal), al tratar de usar el mtodo establecerDepartamento() se habra producido un error,
porque la clase padre no tiene este mtodo. Es decir, la herencia significa que la clase derivada
hereda todo lo que hay en la clase padre, pero la clase padre no hereda nada de la clase derivada.

La herencia en JavaScript tiene las siguientes caractersticas:

No se soporta la herencia mltiple. Es decir, una clase slo puede derivar de una clase
padre, no de dos o ms.
Se soporta la sobrescritura de mtodos. Un mtodo de la clase derivada puede tener el
mismo nombre e, incluso, el mismo esquema, que un mtodo de la clase padre. Que se
invoque a uno u otro depender, en todo caso, de la clase a la que pertenezca el objeto.
No se soporta la sobrecarga de mtodos. Es decir, no se pueden crear, en una misma
clase, dos mtodos con el mismo nombre y diferente esquema, ya que slo se reconocer
el ltimo.

INSTRUCTOR: CLAROS VASQUEZ Carlos Orlando cclaros@senati.pe Pg. N 09

You might also like