martes, 22 de enero de 2013

Herencia en PHP

La herencia es una propiedad de la programación orientada a objetos (POO), no únicamente de PHP.
La herencia nos permite utilizar una clase como base para otra, y asi podemos extender sus funcionalidades, o diseñar de una manera mejor nuestro sistema.

Por ejemplo, vamos a definir la clase persona de la siguiente manera:
class Persona {
	var $nombre;
	var $apellido;
	var $dni;
	var $calle;
 
 
	function __construct($nombre, $apellido, $dni, $calle) {
		print "Creando objecto de la clase Persona con nombre completo: " .
			   $nombre . " " . $apellido . " y DNI: " . $dni . "\n";
		$this->nombre = $nombre;
		$this->apellido = $apellido;
		$this->dni = $dni;
		$this->calle = $calle;
	}

	function mostrarDatos(){
		print "Nombre: " .  $this->nombre .  "\n";
		print "Apellido: " .  $this->apellido .  "\n";
		print "DNI: " .  $this->dni . "\n";
		print "Calle: " .  $this->calle . "\n\n";
	}
}
Como podemos ver, la clase persona tiene 4 atributos: nombre, apellido, dni y calle; ademas de la funcion mostrarDatos.

Ahora imaginemos que queremos construir un sistema en el cual tenemos compradores y vendedores.
Ambos heredaran de persona, pero cada clase tendrá sus propias propiedades:
  • Los vendedores tienen un atributo especifico que undica su número de vendedor. También pueden vender productos, cosa que no pueden los compradores.
  • A su vez, los compradores pueden comprar productos y no tienen número de vendedor, ni nada.

Estas clases quedarían definidas de la siguiente manera:

class Vendedor extends Persona {
	var $identificadorVendedor;

	function __construct($nombre, $apellido, $dni, $calle, $identificadorVendedor) {
		parent::__construct($nombre, $apellido, $dni, $calle);
		$this->identificadorVendedor = $identificadorVendedor;
		print  $nombre . " es un VENDEDOR \n";
	}

	function vender() {
		print "Vendedor " .  $this->nombre . " con numero: " . $this->identificadorVendedor . ", vende un producto \n";
	}
}

class Comprador extends Persona {
	
	function comprar() {
		print "Comprador " .  $this->nombre . " compra un producto\n";
	}
}
Ahora que tenemos nuestras clases definidas vamos a probar a crear un par de vendedores y compradores, y ver que podemos hacer con ellos.
$pedro = new Vendedor ("Pedro", "Sanchez", "40123903K", "Calle Falsa 123", "4214");
$juan = new Comprador("Juan", "Gabilondo", "10392129E", "Calle Loca n: 2");

$pedro->vender();
$juan->comprar();

La salida que obtenemos es la siguiente:
Creando objecto de la clase Persona con nombre completo: Pedro Sanchez y DNI: 40123903K
Pedro es un VENDEDOR 
Creando objecto de la clase Persona con nombre completo: Juan Gabilondo y DNI: 10392129E
Vendedor Pedro con numero: 4214, vende un producto 
Comprador Juan compra un producto

Podemos observar varias cosas:
  1. Desde el constructor de Vendedor hemos llamado al constructor del padre (clase Persona) mediante: parent::__construct($nombre, $apellido, $dni, $calle); 
  2. Que en el constructor de Vendedor, aparte de la llamada al padre hemos asignado el atributo identificadorVendedor, y hemos puesto una salida por pantalla.
  3. Cuando hemos definido la clase Comprador no hemos implementado el constructor. No ha hecho falta, pues no queriamos un comportamiento diferente al del padre (clase Persona). Y como podemos observar ha funcionado.
Podríamos probar a intentar llamar a la funcion vender desde un comprador, pero no daria ninguna salida.

Lo que si podemos hacer es llamar a los metodos del padre.
$pedro->mostrarDatos();
$juan->mostrarDatos();

Nos daría la siguiente salida:
Nombre: Pedro
Apellido: Sanchez
DNI: 40123903K
Calle: Calle Falsa 123

Nombre: Juan
Apellido: Gabilondo
DNI: 10392129E
Calle: Calle Loca n: 2

Se puede ver que de Pedro, que es vendedor, no nos apare su número de vendedor.
Si quisieramos que saliese este dato deberíamos sobreescribir la funcion mostrarDatos en la clase Vendedor. Sobreescribir consiste en escribir exactamente la misma funcion en la clase hija.

Quedaría de la siguiente manera:
class Vendedor extends Persona {
	var $identificadorVendedor;

	function __construct($nombre, $apellido, $dni, $calle, $identificadorVendedor) {
		parent::__construct($nombre, $apellido, $dni, $calle);
		$this->identificadorVendedor = $identificadorVendedor;
		print  $nombre . " es un VENDEDOR \n";
	}

	function vender() {
		print "Vendedor " .  $this->nombre . " con numero: " . $this->identificadorVendedor . ", vende un producto \n";
	}

	function mostrarDatos(){
		print "Nombre: " .  $this->nombre .  "\n";
		print "Apellido: " .  $this->apellido .  "\n";
		print "DNI: " .  $this->dni . "\n";
		print "Calle: " .  $this->calle . "\n";
		print "Numero de vendedor: " . $this->identificadorVendedor ."\n\n";
	}
}

Si ejecutamos mostrarDatos con Pedro y Juan, podemos ver que la salida cambia para Pedro (que es vendedor), pero no para Juan (que es comprador).
Nombre: Pedro
Apellido: Sanchez
DNI: 40123903K
Calle: Calle Falsa 123
Numero de vendedor: 4214

Nombre: Juan
Apellido: Gabilondo
DNI: 10392129E
Calle: Calle Loca n: 2

Podemos descargar los códigos de ejemplo en los siguientes enlaces:

Clases, Objetos y Constructores en PHP


Para entender los constructores hay que tener claro el concepto de clase y objeto.

No voy a utilizar definiciones formales, ni voy a referenciar a otros sitios. Si no queda claro, siempre se puede preguntar e intentare aclararlo cuando sea posible.

CLASES

Una clase es la definición de como son las cosas.
Por ejemplo, podemos tener una clase Persona, a la cual le asignaremos una altura y un nombre.
Quedaría definida tal que así:
class Persona {
   var $nombre;
   var $altura;
}

Esta es la definición básica de una clase persona.
A cada variable interna que creamos la llamaremos atributos. Así pues Persona tiene dos atributos: nombre y altura.

 Ahora pasaremos a ver los objetos y su relación con las clases.

OBJETOS

Los objetos son cosas concretas de un determinado tipo. Al tipo al que nos referimos será la clase.
Por ejemplo, tenemos la clase persona, así que ahora podemos definir diferentes objetos de esa clase.

$juan = new Persona;
$jesus = new Persona;
$ana = new Persona;

Acabamos de crear 3 objetos de tipo Persona (también se puede decir que hemos creado 3 instancias de la clase Persona).

Ahora podríamos acceder a ellos y asignarles diferentes valores a sus atributos.
Por ejemplo:

$juan->nombre = "Juan";
$juan->altura = 182;

$jesus->nombre = "Jesus Alfonso";
$jesus->altura = 168;

$ana->nombre = "Ana";
$ana->altura = 162;
No debemos confundir el nombre de la variable de los objetos, en este caso: $juan, $jesus y $ana con el atributo nombre que le hemos dado a esta clase "Juan", "Jesus Alfonso", "Ana".
Ni es obligatorio que una clase tenga atributo nombre, ni este ha de ser el mismo que el de la variable. Simplemente debemos nombrar la variable de la manera que mejor nos recuerde que contiene.

Podemos tambien imprimir los datos de los objetos:
print "Nombre: " . $juan->nombre . ", altura: ". $juan->altura;
print "Nombre: " . $jesus->nombre . ", altura: ". $jesus->altura;
print "Nombre: " . $ana->nombre . ", altura: ". $ana->altura;

CONSTRUCTORES

A la hora de crear objetos nos puede venir bien tener constructores, que son funciones que se ejecutan al crear el objeto de una clase.

Los podemos utilizar para inicializar valores de la clase, enlazar el objeto con otros objetos, mostrar mensajes por pantalla, etc. para lo que queramos básicamente.
Para crear un constructor hay que definir una función llamada __construct en la cual definiremos lo que vamos a hacer.
En la clase Persona que vimos anteriormente vamos a crear un constructor que nos muestre un mensaje por pantalla e inicialice la altura y nombre de los objetos que creemos posteriormente.

class Persona {
 var $nombre; // esto es un atributo
 var $altura; // esto es un atributo

 function __construct($nombre, $altura){ // este es el constructor
  print "Creando objecto de la clase Persona con nombre " . 
    $nombre . " y altura " . $altura . "cm";
  $this->nombre = $nombre;  
  $this->altura = $altura;
 }
}
Nota: Como podemos ver, hacemos uso de la variable $this. Esta variable nos sirve para acceder a los parámetros y funciones de la clase.

En este caso accedemos al parámetro nombre y altura.

Gracias al constructor ahora podemos crear objetos de manera más rápida.
$juan = new Persona("Juan", 182);
$jesus = new Persona("Jesus Alfonso", 168);
$ana = new Persona("Ana", 162);

Ahora ya podríamos acceder a estos objetos, y a sus variables.
print "Nombre: " . $juan->nombre . ", altura: ". $juan->altura;
print "Nombre: " . $jesus->nombre . ", altura: ". $jesus->altura;
print "Nombre: " . $ana->nombre . ", altura: ". $ana->altura;
Nota: En este caso no se hace uso de la variable $this, para acceder a los parámetros, sino que se utiliza el nombre del objeto en concreto. La variable $this se utiliza sólo dentro de la definición de la clase.

La salida que obtenemos es la siguiente:

Creando objecto de la clase Persona con nombre Juan y altura 182cm
Creando objecto de la clase Persona con nombre Jesus Alfonso y altura 168cm
Creando objecto de la clase Persona con nombre Ana y altura 162cm
Nombre: Juan, altura: 182
Nombre: Jesus Alfonso, altura: 168
Nombre: Ana, altura: 162

Se pueden bajar los archivos usados de ejemplo desde los siguientes enlaces:
Ejemplo 1: clase básica.
Ejemplo 2: clase con constructor.

miércoles, 20 de junio de 2012

Formatear notas en StickyNotes

Para manejar notas en Windows tenemos por defecto instalado el StickyNotes.

No es muy potente, pero el hecho de que venga por defecto ya es un aliciente para esos momentos en los que tenemos que apuntar algo.

En esta entrada os pongo una captura en la cual podemos ver los comandos para utilizar las notas.

Figura 1: Uso de accesos directos en StickyNotes.

El simbolo ^ se corresponde a la tecla Ctrl, así ^B significa mantener pulsado la tecla Ctrl y luego la tecla B.

También recordaros que podemos cambiar el color de la nota con el boton derecho, lo cual nos facilitará diferenciar temas por los colores que usemos.

lunes, 2 de abril de 2012

Sincronizar Notas en Windows 7



Voy a explicar como sincronizar las notas que podemos realizar en windows 7 (utilizando StickyNotes).


Para ello vamos a ayudarnos de Dropbox y los enlaces simbolicos en ntfs que explique aqui.

No es que sea algo realmente útil, pues podriamos utilizar directamente un servicio como Evernote.
Es simplemente una manera de mostrar la ventajas de usar los enlaces simbolicos en windows, que poco tienen que ver con los accesos directos, y cuyo comportamiento puede resultar algo dificil de entender.

Por ahora sólo dire como realizar la sincronización, sin meternos en mas profundidad.

Vamos a dar por supuesto que tenemos una cuenta de Dropbox, y que lo tenemos instalado en el equipo.

Además debemos tener instalado Junction. Podemos ver como se descarga y utiliza aqui.

Paso 1
Creamos una carpeta llamada Sticky Notes en nuestra carpeta de Dropbox.
En mi caso estará en:
C:\Users\Usuario\Dropbox\Sticky Notes.

Paso 2
Borramos la carpeta en la cual estan almacenadas las notas en el equipo.
La ruta es:
C:\Users\Usuario\AppData\Roaming\Microsoft\Sticky Notes
Paso 3
Creamos un enlace Simbolico de nuestra carpeta de Dropbox a la carpeta de las notas. Para ello abrimos un terminal y escribimos lo siguiente.
junction "C:\Users\Usuario\AppData\Roaming\Microsoft\Sticky Notes" "C:\Users\Usuario\Dropbox\Sticky Notes"

Con estos pasos ya lo tendríamos hecho.
Lo bueno de este método es que viene totalmente integrado en Windows 7.

¿Lo malo? Pues algunas cosillas, pero una de ellas es que no funciona del todo perfecto si ambos equipos se estan manejando a la vez.
Pero bueno, si entendemos el concepto lo podremos utilizar para cualquier programa que querramos.

jueves, 28 de julio de 2011

Decoradores en python (I)

Llevo poco tiempo programando en python, y una de las cosas que más me ha sorpendido es el tema de los decoradores. Estan basado en el patron decorador, y existen tambien en otros lenguajes, pero en python esta muy bien integrado. Los decoradores nos sirven para añadir nuevas funcionalidades a codigo ya existente, o reutilizar código de forma más eficiente, y sobre todo tambien, para que quede el codigo más legible. En está pagina podemos ver que lo utiliza para evitar la repetición de código, y para que quede más clara. A continuación voy a poner un ejemplo muy simple de decorador, que simplemente nos dice cuando se ejecuta la parte perteneciente al decorador con un print: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 # Nuestro decorador def saluda_antes(funcion): print "Codigo antes de decorar la funcion" def nueva_funcion(*args, **kwargs): print "Ejecuto la funcion decorada" return funcion(*args, **kwargs) print "Codigo despues de decorar la funcion" return nueva_funcion # Nuestra funcion def sumar(a, b): print "Ejecutando suma" return a+b # Main if __name__ == '__main__': sol = sumar(2, 3) print "Solucion {0}\n".format(sol) print "Decoramos la funcion_______________" sumar = saluda_antes(sumar) print "Funcion ya decorada________________\n" sol = sumar(2, 3) print "Solucion {0}".format(sol) Que nos genera la siguiente salida: Ejecutando suma Solucion 5 Decoramos la funcion_______________ Codigo antes de decorar la funcion Codigo despues de decorar la funcion Funcion ya decorada________________ Ejecuto la funcion decorada Ejecutando suma Solucion 5 En el primer bloque vemos la funcion sumar a secas. En el segundo la salida que nos muestra es la que obtenemos mientras se aplica el decorador. Y por ultimo tenemos el resultado de lanzar la funcion con el decorador aplicado. Otra manera de lanzar el decorador es poniendo la @nombre_decorador encima de la función. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # Nuestro decorador def saluda_antes(funcion): print "Codigo antes de decorar la funcion" def nueva_funcion(*args, **kwargs): print "Ejecuto la funcion decorada" return funcion(*args, **kwargs) print "Codigo despues de decorar la funcion" return nueva_funcion # Nuestra funcion @saluda_antes def sumar(a, b): print "Ejecutando suma" return a+b # Main if __name__ == '__main__': sol = sumar(2, 3) print "Solucion {0}".format(sol) Que genera una salida ligeramente diferente: Codigo antes de decorar la funcion Codigo despues de decorar la funcion Ejecuto la funcion decorada Ejecutando suma Solucion 5 Podemos ver que lo primero que se ejecuta es el código que hay al decorar la funcion, seguido por el código del decorador, y por último el de la funcion. Creo que queda claro, pero solo quiero aclarar que el codigo que se ejecuta al decorar la funcion (al principio), sólo se ejecuta una única vez. Si hicieramos 4 llamadas seguidas, tendriamos algo tal que así: Codigo antes de decorar la funcion Codigo despues de decorar la funcion Ejecuto la funcion decorada Ejecutando suma Solucion 5 Ejecuto la funcion decorada Ejecutando suma Solucion 5 Ejecuto la funcion decorada Ejecutando suma Solucion 5 Ejecuto la funcion decorada Ejecutando suma Solucion 5 Y hasta aquí lo que se daba. Volvere con más operadores cuando aprenda un poco más sobre ellos (paso de parametros, autocreacion de decoradores, etc).

viernes, 3 de junio de 2011

Instalación de Redmine sobre Debian Squeeze

La versión de Redmine que vamos a instalar es la 1.2.

Instalamos dependencias:
sudo aptitude install mysql-server
sudo aptitude install apache2
sudo aptitude install ruby
sudo aptitude install rails
sudo aptitude install rake rubygems
sudo aptitude install libmysql-ruby libopenssl-ruby
sudo gem install rails -v=2.1.2
sudo aptitude install g++ make ruby-dev apache2-dev
sudo aptitude install libcurl4-openssl-dev
sudo aptitude install subversion

Configuración MySQL
mysql -u root -p

create database redmine character set utf8;
grant all on redmine.* to ‘redmine’ identified by ‘*****’;

Si queremos que se utilice como motor de búsqueda InnoDB, creamos el fichero innodb.cnf:
sudo vi /etc/mysql/conf.d/innodb.cnf

Con la siguiente información:
[mysqld]
default-storage-engine = InnoDB

Y reiniciamos el servidor:
sudo /etc/init.d/mysql restart

Instalamos passenger
Version instalada: 3.0.9
sudo gem install passenger
cd /var/lib/gems/1.8/gems/passenger-3.0.9/bin/
sudo ./passenger-install-apache2-module
sudo ln -s /var/lib/gems/1.8/gems/passenger-3.0.9/ /usr/lib/passenger

Configuración de Apache para Passenger
En la ruta /etc/apache2/mods-available/ creamos los ficheros passenger.load y passenger.conf, con la siguiente informacion:

PASSENGER.LOAD
sudo vi /etc/apache2/mods-available/passenger.load

LoadModule passenger_module /var/lib/gems/1.8/gems/passenger-3.0.7/ext/apache2/mod_passenger.so

PASSENGER.CONF
sudo vi /etc/apache2/mods-available/passenger.conf
PassengerRoot /usr/lib/passenger
PassengerRuby /usr/bin/ruby1.8
PassengerDefaultUser www-data

Y ahora los habilitamos:
cd /etc/apache2/mods-enabled/
sudo ln -s ../mods-available/passenger.load
sudo ln -s ../mods-available/passenger.conf

Y reiniciamos apache:
sudo /etc/init.d/apache2 reload

Instalamos RedMine
Descargamos RedMine (Version instalada 1.2)
cd /usr/local/lib
sudo svn co http://redmine.rubyforge.org/svn/branches/1.2-stable redmine-1.2

Instalamos dependencias
sudo gem install -v=0.4.2 i18n
sudo gem install -v=2.3.11 rails
sudo gem install rake -v'0.8.7'
sudo gem uninstall rake -v'0.9.0'

Configuramos fichero enviroment:
sudo nano redmine-1.2/config/environment.rb

y añadimos la siguiente línea:
config.action_controller.session = { :key => "_myapp_session", :secret => "tengoqueponeraqui30caracteresynosequecojonesponer" }

Instalamos la base de datos de RedMine:
cd /usr/local/lib/redmine-1.2/
sudo cp config/database.yml.example config/database.yml
sudo rake db:migrate RAILS_ENV="production"

Terminamos de configurar el RedMine:
cd /usr/local/lib/redmine-1.2/
sudo mkdir tmp public/public_assets
sudo chown -R www-data:www-data files log tmp public/public_assets
sudo chmod -R 755 files log tmp public/public_assets

Configuracion de Apache para soportar Redmine
cd /etc/apache2/sites-enabled
sudo rm 000-default

Creamos el fichero /etc/apache2/sites-available/redmine
sudo nano /etc/apache2/sites-available/redmine

Con la siguiente información:
<VirtualHost *:80>
  DocumentRoot /usr/local/lib/redmine-1.2/public
  <Directory /usr/local/lib/redmine-1.2/public>
     AllowOverride None
  </Directory>
</VirtualHost>

Y lo habilitamos:
cd /etc/apache2/sites-enabled
sudo ln -s ../sites-available/redmine 000-default

Y por ultimo reiniciamos apache:
sudo /etc/init.d/apache2 reload

Con esto ya debería estar funcionando.
Por lo menos así fue en mi caso, problem?

viernes, 25 de marzo de 2011

Mantener programas activos al cerrar el terminal

Muchas veces hemos abierto programas desde una terminal y queremos dejarlos activos al cerrar.
O bien si queremos dejar abierto algo en una maquina remota, también podemos hacerlo.

Para ello segun se esta ejecutando el programa presionamos Ctrl + z y después escribimos:
bg
disown


Ahora ya podemos cerrar el terminal sin problemas.