Programación con funciones, clases y arreglos para artistas

Definición y uso

Vamos a llegar a la idea de clase partiendo de un ejemplo donde dibujamos un objeto simple como un círculo:

var circulo = { 
	x: 100, 
	y: 100, 
	d: 50
}

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);
  ellipse(circulo.x, circulo.y, circulo.d, circulo.d);
}

Ahora viene una revelación interesante y es que nosotros sabemos que los objetos almacenan propiedades, pero esas propiedades no tienen porqué ser simples datos, pueden ser funciones:

var circulo = { 
	x: 100, 
	y: 100, 
	d: 50,
	saludar: function() { 
		print("¡Hola :3! soy un círculo")
	}
}

Para llamar una función de un objeto simplemente accederemos a su nombre y las ejecutaremos como una función normal:

function setup() {
  createCanvas(400, 400);
  circulo.saludar();
}

Con esto en mente no sería descabellada la idea de incluir en el objeto su propia función draw para dibujarse a sí misma, ¿verdad?

var circulo = { 
	x: 100, 
	y: 100, 
	d: 50,
	saludar: function() { 
		print("¡Hola :3! soy un círculo")
	},
	draw: function() {
		ellipse(circulo.x, circulo.y, circulo.d, circulo.d);
	}
}

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);
  circulo.draw();  // dibujamos el círculo a sí mismo
}

¡Funciona!

Muy bien muy bien, ¿pero por qué estamos trabajando con funciones si esta es la lección de las clases? Ahora mismo lo váis a descubrir.

La necesidad de las clases

Ahora supongamos que quisiéramos dibujar otro círculo a parte del que ya tenemos. ¿Qué haríamos? ¿Copiamos toda la estructura del circulo para crear otro circulo diferente? Nada nos impide hacerlo:

var circulo = { 
	x: 100, 
	y: 100, 
	d: 50,
	saludar: function() { 
		print("¡Hola :3! soy un círculo")
	},
	draw: function() {
		ellipse(circulo.x, circulo.y, circulo.d, circulo.d);
	}
}

var circulo2 = { 
	x: 300, 
	y: 300, 
	d: 50,
	saludar: function() { 
		print("¡Hola :3! soy un círculo")
	},
	draw: function() {
		ellipse(circulo2.x, circulo2.y, circulo2.d, circulo2.d);
	}
}

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);
  circulo.draw();
  circulo2.draw();
}

¿Y si quisiéramos dibujar 10 círculos tendríamos que crear 10 veces un objeto con las mismas propiedades?

En seguida se nota que algo no cuadra, debería existir una forma de manejar esto sin repetir tanto código... y así es amigos, esa forma son las clases.

Las clases sirven como moldes para generar objetos con propiedades y funciones comunes en sus estructuras.

Así que en lugar de crear tantos objetos vamos a crear una clase círculo para generar círculos:

class Circulo {
  
}

Bien ya tenemos la clase definida.

Ahora necesitamos una forma de definir sus propiedades internas, eso se hace definiendo una función especial que tienen llamado constructor que recibe las propiedades que queremos asignar al objeto:

class Circulo {
	constructor(x, y, d) {
		alert("Soy un círculo cuyas propiedades valen", x, y, d)
	}
}

Fijaros como no tenemos que usar la palabra function para crear la función constructor.

Muy bien, ahora tenemos que usar esta clase para generar un círculo, eso lo haremos instanciando un objeto a partir de ella con la instrucción new:

var circulo = new Circulo(100, 100, 50);

function setup() {
  createCanvas(400, 400);
}

Como véis así hemos conseguido almacenar en la variable circulo unas propiedades.

Por cierto, de la misma forma que las variables dentro de los objetos se denominan propiedades, las funciones reciben el nombre de métodos. Por tanto la función constructor en realidad se denomina método constructor.

Sabiendo eso vamos a añadir el método draw a la clase Circulo para dibujar la figura:

class Circulo {
	constructor(x, y, d) {
		alert("Soy un círculo cuyas propiedades valen", x, y, d)
	}

	draw(){
		ellipse(x, y, d, d);
	}
}

var circulo = new Circulo(100, 100, 50);

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);
  circulo.draw();
}

Esta es la única forma como por ahora podemos suponer que se hace, pero lamentablemente esto no va a funcionar. Nos dará un error indicando que no se encuentra la propiedad x para poder dibujar el círculo.

¿Por qué ocurre esto? Bueno, no sé si recordaréis que antes para dibujar el círculo a sí mismo lo que hacíamos era pasar a la función ellipse los propios valores del objeto circulo. En las clases no podemos hacerlo de esa forma, además la idea de que los valores son accesibles entre los métodos haciendo referencia al nombre no funciona de esa forma.

Sí, existe una forma de acceder a las propiedades entre los métodos, pero para entenderla necesitamos aprender el concepto instancia.