La reproducción de los objetos
En el colegio me enseñaron que “los seres vivos nacen, crecen, se reproducen y mueren”. Por lo visto los HTMLDoc son seres vivos. Nacen cuando los crea una llamada a “new”. Crecen cuando les añadimos código HTML con cosas como “insertAfter” o “insertBefore”. Mueren cuando se les hace una llamada a “clear” cuando eliminamos nodos.
Y se reproducen, porque un objeto puede
generar otros de su misma clase mediante “getElement”. Que es el
único método que me queda por pagaros. Así que ahí va:
def
getElement(start) if not (0..(@nodes.length - 1)).include?(start) raise 'Element out of range' end ending = findEndOfTag(start) new_element = HtmlDoc.new new_element.type = :node new_element.nodes = @nodes new_element.starts_at = start new_element.ends_at = ending new_element.document = typeOf == :document ? self : @document new_element.document.nodes_created.push(new_element) return new_element end |
ending = findEndOfTag(start) |
… que asigna a “ending” la
posición en que acaba el código HTML del objeto. Y para ello
llamamos al método “findEndOfTag”... que aún no hemos definido.
¡Jolín! ¡Ahora que estábamos casi acabando y nos aparece otro
método que dejaremos para más adelante!
Tranquis, que tampoco es para tanto, y sigamos. Creamos un nuevo objeto de la clase HTMLDoc para representar el elemento:
new_element = HtmlDoc.new |
… e inicializamos sus valores, par
decir que es un nodo (no un documento completo), que comparte los
nodos de su padre (que en algo se tenía que parecer a él), indicar
donde comienza y acaba y señalar al documento al que pertenece:
new_element.type
= :node new_element.nodes = @nodes new_element.starts_at = start new_element.ends_at = ending new_element.document = typeOf == :document ? self : @document |
Fijaos en que las invocaciones a “self”
o “typeOf” se refieren al objeto padre, sobre el que estamos
invocando el método, no al hijo que estamos creando. Y recordad que
podemos modificar un objeto desde otro porque definimos los accesores
como “protegidos”.
Y otra cosa: en la asignación "new_element.nodes = @nodes" hay que tener en cuenta que cuando asignamos a una variable un objeto en Ruby NO creamos una nueva copia del objeto. De modo que el atributo @nodes del nodo que acabamos de crear y el de su padre harán referencia a un mismo objeto.
Como prueba valga el siguiente ejemplo:
Para crear copias de un objeto tenemos el método clone
Y otra cosa: en la asignación "new_element.nodes = @nodes" hay que tener en cuenta que cuando asignamos a una variable un objeto en Ruby NO creamos una nueva copia del objeto. De modo que el atributo @nodes del nodo que acabamos de crear y el de su padre harán referencia a un mismo objeto.
Como prueba valga el siguiente ejemplo:
$ irb irb(main):001:0> a = [1,2,3] => [1, 2, 3] irb(main):002:0> b = a => [1, 2, 3] irb(main):003:0> a[2] = 1 # Modificamos el array original => 1 irb(main):004:0> b => [1, 2, 1] irb(main):005:0> # ... y b también ha sido modificado |
Para crear copias de un objeto tenemos el método clone
irb(main):006:0* c = a.clone # c es ahora una copia de a => [1, 2, 1] irb(main):007:0> a[1]=100 # Si modificamos a... => 100 irb(main):008:0> c => [1, 2, 1] irb(main):009:0> # c sigue igual |
Sigamos. Al documento original hay que
decirle que hemos creado un nuevo elemento a partir de él, para que
vaya llevando la cuenta:
new_element.document.nodes_created.push(new_element) |
return new_element |
No hay comentarios:
Publicar un comentario