{"id":442,"date":"2022-10-06T12:15:03","date_gmt":"2022-10-06T10:15:03","guid":{"rendered":"http:\/\/quadern-programacio.recursos.uoc.edu\/?page_id=442"},"modified":"2022-10-07T13:26:39","modified_gmt":"2022-10-07T11:26:39","slug":"9-2-objetos","status":"publish","type":"page","link":"http:\/\/quadern-programacio.recursos.uoc.edu\/es\/9-2-objetos\/","title":{"rendered":"9.2. Objetos"},"content":{"rendered":"<p>A medida que nuestros programas van creciendo en complejidad, hemos visto que suele ser conveniente encapsular partes del c\u00f3digo en funciones o utilizar variables para evitar redundancias. Con la introducci\u00f3n de objetos en nuestro c\u00f3digo daremos un paso m\u00e1s all\u00e1 y nos adentraremos en la programaci\u00f3n orientada a objetos (OPP, <em>object-oriented programming<\/em>), un paradigma de programaci\u00f3n en el que comenzaremos a pensar en nuestros programas como en peque\u00f1as estructuras que se combinan para crear otras estructuras m\u00e1s complejas. Siempre ser\u00e1 mejor crear y mantener estructuras modulares m\u00e1s peque\u00f1as de c\u00f3digo que intentar escribir un programa monol\u00edtico con todas las funcionalidades.<\/p>\n<p>Los objetos no dejan de ser una manera de vincular variables y funciones en una peque\u00f1a estructura. Como ya sabemos trabajar tanto con variables como con funciones, los objetos no ser\u00e1n m\u00e1s que una manera m\u00e1s conveniente y estructurada de combinar lo que ya sabemos hacer.<\/p>\n<h3>Propiedades y m\u00e9todos<\/h3>\n<p>Estas variables y funciones que vinculamos, cuando hablamos de objetos, las llamaremos propiedades y m\u00e9todos. Su funcionamiento es completamente el mismo que el de las variables y funciones que ya conocemos, pero cuando est\u00e9n asociadas a un objeto nos referiremos a estas como propiedades y m\u00e9todos.<\/p>\n<p>De esta manera, un objeto no es m\u00e1s que un conjunto de valores (propiedades) asociados entre s\u00ed con una serie de acciones y comportamientos (m\u00e9todos).<\/p>\n<p>Pongamos como ejemplo que queremos crear un paisaje en nuestro <em>sketch<\/em>. Si seguimos la l\u00f3gica de la programaci\u00f3n orientada a objetos, podr\u00edamos pensar en el paisaje final como una estructura compleja compuesta de otras estructuras m\u00e1s peque\u00f1as (flores, \u00e1rboles, cielo, nubes\u2026), y cada una de estas estructuras m\u00e1s peque\u00f1as podr\u00eda ser un objeto.<\/p>\n<p>Si elegimos uno de estos objetos, la flor, por ejemplo, podr\u00edamos darle una serie de propiedades: posici\u00f3n, tama\u00f1o y n\u00famero de p\u00e9talos. Tambi\u00e9n alg\u00fan comportamiento: crecer y que se muestre. Por lo tanto, deberemos contar con las siguientes variables y funciones:<\/p>\n<pre>let posX, posY;\r\nlet size;\r\nlet numPetals;\r\n\r\nfunction grow(){}\r\nfunction display(){}<\/pre>\n<h3>Clases y objetos<\/h3>\n<p>Cada flor individual podr\u00e1 tener distinto tama\u00f1o, posici\u00f3n o n\u00famero de p\u00e9talos, pero todas las flores responder\u00e1n siempre a esta misma estructura de propiedades y m\u00e9todos. A esta estructura o plantilla de flor la llamamos <strong>clase<\/strong> y a cada una de las flores individuales que creemos a partir de la plantilla la llamaremos <strong>objeto<\/strong>. Por lo tanto, tendremos una clase flor con la que crearemos distintos objetos flor. Veamos ahora c\u00f3mo crear una clase en P5.<\/p>\n<p>Lo primero que debemos hacer es utilizar la palabra clave <span class=\"courier\">class<\/span> seguida del nombre de nuestra clase, que por convenci\u00f3n pondremos en may\u00fascula.<\/p>\n<pre>class Flower {\r\n  \/\/ Nuestra clase (plantilla) para crear flores\r\n}<\/pre>\n<p>A continuaci\u00f3n, crearemos dentro de la clase su <strong>constructor<\/strong>, que define la forma en la que m\u00e1s adelante crearemos nuestros objetos. En el constructor definimos qu\u00e9 par\u00e1metros necesitaremos darle a nuestro objeto flor para su creaci\u00f3n y su relaci\u00f3n con las propiedades que definamos.<\/p>\n<pre>\/\/ De la misma manera que para crear un c\u00edrculo tenemos:\r\n\/\/ circle(posX, posY,)\r\n\/\/ Para crear nuestra flor queremos algo as\u00ed:\r\n\/\/ Flower(posX, posY, numPetals);<\/pre>\n<p>De manera que nuestro constructor deber\u00e1 ser algo similar a lo siguiente:<\/p>\n<pre>class Flower {\r\n  constructor(posX, posY, numPetals) {\r\n  }\r\n}<\/pre>\n<p>Y dentro del constructor establecemos la relaci\u00f3n entre estos par\u00e1metros y las propiedades de nuestra clase:<\/p>\n<pre>class Flower {\r\n  constructor(posX, posY, numPetals) {\r\n    this.posX = posX;\r\n    this.posY = posY;\r\n    this.numPetals = numPetals;\r\n  }\r\n}<\/pre>\n<p>Dentro de la clase estamos creando y accediendo a sus propiedades a trav\u00e9s de la palabra clave <span class=\"courier\">this<\/span>. De esta manera, le decimos al programa que no son unas variables cualesquiera, sino que se trata de propiedades relativas a esta (<em>this<\/em>) clase. A continuaci\u00f3n, les asignamos valores que les pasamos como par\u00e1metro. De primeras, este c\u00f3digo puede parecer algo confuso, ya que los nombres de los par\u00e1metros y de las propiedades son los mismos, aunque no tiene por qu\u00e9 ser as\u00ed. Para hacer el c\u00f3digo m\u00e1s comprensible (sobre todo cuando creamos nuestras primeras clases), puede resultar conveniente que por ejemplo a los par\u00e1metros les a\u00f1adamos alg\u00fan prefijo para aclararnos:<\/p>\n<pre>class Flower {\r\n  constructor(_posX, _posY, _numPetals) {\r\n    this.posX = _posX;\r\n    this.posY = _posY;\r\n    this.numPetals = _numPetals;\r\n  }\r\n}<\/pre>\n<p>O tambi\u00e9n as\u00ed:<\/p>\n<pre>class Flower {\r\n  constructor(pPosX, pPosY, pNumPetals) {\r\n    this.posX = pPosX;\r\n    this.posY = pPosY;\r\n    this.numPetals = pNumPetals;\r\n  }\r\n}<\/pre>\n<p>En este caso, todas las propiedades que hemos definido dentro del constructor est\u00e1n asociadas a par\u00e1metros que le pasamos, pero no tiene que ser as\u00ed. Podemos tener propiedades que definamos directamente:<\/p>\n<pre>class Flower {\r\n  constructor(pPosX, pPosY, pNumPetals) {\r\n    this.posX = pPosX;\r\n    this.posY = pPosY;\r\n    this.numPetals = pNumPetals;\r\n    this.size = 20;\r\n    this.flowerColor = \u201clightblue\u201d;\r\n  }\r\n}<\/pre>\n<p>Tras haber definido el constructor de nuestra clase, mediante el cual crearemos los objetos, podemos definir m\u00e9todos de la clase. Por ejemplo, podr\u00edamos tener un m\u00e9todo para hacer crecer la flor:<\/p>\n<pre>class Flower {\r\n  constructor(pPosX, pPosY, pNumPetals) {\r\n    this.posX = pPosX;\r\n    this.posY = pPosY;\r\n    this.size = 20;\r\n    this.numPetals = pNumPetals;\r\n    this.flowerColor = \"lightblue\";\r\n  }\r\n  \r\n  grow() {\r\n    this.size *= 1.01;\r\n  }\r\n}<\/pre>\n<p>De esta manera, cada vez que llamemos al m\u00e9todo <span class=\"courier\">grow()<\/span>, el tama\u00f1o de la flor aumentar\u00e1 un 1 %. Si queremos visualizar la flor en nuestro <em>sketch<\/em>, deberemos crear otro m\u00e9todo que se encargue de dibujarla utilizando sus propiedades:<\/p>\n<pre>class Flower {\r\n  constructor(pPosX, pPosY, pNumPetals) {\r\n    this.posX = pPosX;\r\n    this.posY = pPosY;\r\n    this.size = 20;\r\n    this.numPetals = pNumPetals;\r\n    this.flowerColor = \u201clightblue\u201d;\r\n  }\r\n  \r\n  grow() {\r\n    this.size *= 1.1;\r\n  }\r\n\r\n  display() {\r\n    for(let i = 0; i &lt; this.numPetals; i++) {\r\n      noStroke();\r\n      fill(this.flowerColor);\r\n      let angle = 2 * PI \/ this.numPetals * i;\r\n      circle(this.posX + cos(angle) * this.size,\r\n             this.posY + sin(angle) * this.size,\r\n             this.size);\r\n    }\r\n    fill(250);\r\n    circle(this.posX, this.posY, this.size * 1.5);\r\n  }\r\n}<\/pre>\n<p>Aqu\u00ed vemos c\u00f3mo accedemos a las propiedades de la clase usando <span class=\"courier\">this<\/span> para utilizarlas a la hora de dibujar la flor. Para dibujar los p\u00e9talos, estamos utilizando un bucle con el que dibujamos cada p\u00e9talo en su \u00e1ngulo correspondiente dividiendo 360\u00ba (<span class=\"courier\">2 \u00d7 PI<\/span>) entre el n\u00famero de p\u00e9talos y multiplic\u00e1ndolo por el n\u00famero de p\u00e9talo en el que nos encontremos.<\/p>\n<p>Ya tenemos definida nuestra clase, con sus propiedades y sus m\u00e9todos. Lo que debemos hacer ahora es crear alg\u00fan objeto con esta \u00abplantilla\u00bb que hemos creado.<\/p>\n<p>Para ello, la sintaxis es la siguiente:<\/p>\n<pre>function setup(){\r\n  createCanvas(400, 400);\r\n  let flower = new Flower(width * 0.5, height * 0.5, 8);\r\n}<\/pre>\n<p>Usamos la palabra clave new para definir que estamos creando un nuevo objeto de la clase <span class=\"courier\">Flower<\/span> y, a continuaci\u00f3n, entre par\u00e9ntesis le pasamos los par\u00e1metros necesarios para su creaci\u00f3n. En este caso, queremos la flor centrada en el <em>canvas<\/em> y con ocho p\u00e9talos.<\/p>\n<p>Como con el resto de las variables, si queremos acceder a sus propiedades o llamar a sus m\u00e9todos m\u00e1s adelante, es buena pr\u00e1ctica que declaremos la variable al principio del c\u00f3digo para que podamos acceder a esta tanto desde el <span class=\"courier\">setup()<\/span> como\u00a0 desde el <span class=\"courier\">draw()<\/span>. Veamos el proceso entero de definici\u00f3n de la clase y creaci\u00f3n de un objeto basado en la clase:<\/p>\n<p><figure id=\"attachment_276\" aria-describedby=\"caption-attachment-276\" style=\"width: 800px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" class=\"size-full wp-image-276\" src=\"\/wp-content\/uploads\/2022\/10\/PID_00290094_118.jpg\" alt=\"\" width=\"800\" height=\"755\" srcset=\"\/wp-content\/uploads\/2022\/10\/PID_00290094_118.jpg 800w, \/wp-content\/uploads\/2022\/10\/PID_00290094_118-300x283.jpg 300w, \/wp-content\/uploads\/2022\/10\/PID_00290094_118-768x725.jpg 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><figcaption id=\"caption-attachment-276\" class=\"wp-caption-text\">Figura 119. La clase <span class=\"courier\">Flower<\/span> en acci\u00f3n<br \/>Fuente: elaboraci\u00f3n propia.<\/figcaption><\/figure>Hemos escrito la clase al principio de todo, aunque podr\u00eda estar en cualquier otra parte de nuestro c\u00f3digo. De hecho, es muy com\u00fan tener las clases que creemos en distintos archivos. De esta manera, hacemos nuestro c\u00f3digo m\u00e1s modular: una vez que definimos la clase, podemos \u00abolvidarnos\u00bb de esta y solo acudir a su c\u00f3digo si queremos modificar algo espec\u00edfico.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A medida que nuestros programas van creciendo en complejidad, hemos visto que suele ser conveniente encapsular partes del c\u00f3digo en funciones o utilizar variables para evitar redundancias. Con la introducci\u00f3n de objetos en nuestro c\u00f3digo daremos un paso m\u00e1s all\u00e1 y nos adentraremos en la programaci\u00f3n orientada a objetos (OPP, object-oriented programming), un paradigma de [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":[],"acf":[],"_links":{"self":[{"href":"http:\/\/quadern-programacio.recursos.uoc.edu\/es\/wp-json\/wp\/v2\/pages\/442"}],"collection":[{"href":"http:\/\/quadern-programacio.recursos.uoc.edu\/es\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/quadern-programacio.recursos.uoc.edu\/es\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/quadern-programacio.recursos.uoc.edu\/es\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/quadern-programacio.recursos.uoc.edu\/es\/wp-json\/wp\/v2\/comments?post=442"}],"version-history":[{"count":2,"href":"http:\/\/quadern-programacio.recursos.uoc.edu\/es\/wp-json\/wp\/v2\/pages\/442\/revisions"}],"predecessor-version":[{"id":568,"href":"http:\/\/quadern-programacio.recursos.uoc.edu\/es\/wp-json\/wp\/v2\/pages\/442\/revisions\/568"}],"wp:attachment":[{"href":"http:\/\/quadern-programacio.recursos.uoc.edu\/es\/wp-json\/wp\/v2\/media?parent=442"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}